Skip to content

Commit a177f6c

Browse files
content-botxsoar-botaburt-demistoabaumgarten
authored
[Community Contribution] Arduino (demisto#10986)
* [Community Contribution] Arduino (demisto#10894) * "pack contribution initial commit" * Update Arduino.py Commited all changes * Update Arduino.py Fixed Unit testing and linters * Update Arduino.py * Update Arduino.py Co-authored-by: Adam Burt - Demisto <[email protected]> * fixed lint errors Co-authored-by: xsoar-bot <[email protected]> Co-authored-by: Adam Burt - Demisto <[email protected]> Co-authored-by: abaumgarten <[email protected]>
1 parent 6b31e61 commit a177f6c

11 files changed

Lines changed: 795 additions & 0 deletions

File tree

Packs/Arduino/.pack-ignore

Whitespace-only changes.

Packs/Arduino/.secrets-ignore

Whitespace-only changes.
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import socket
2+
3+
import demistomock as demisto # noqa: F401
4+
from CommonServerPython import * # noqa: F401
5+
6+
''' CONSTANTS '''
7+
8+
''' CLIENT CLASS '''
9+
10+
11+
class Server():
12+
def __init__(self, host, port):
13+
self.host = host
14+
self.port = port
15+
self.validate()
16+
17+
def validate(self):
18+
is_ip = False
19+
try:
20+
socket.inet_aton(self.host)
21+
is_ip = True
22+
except socket.error:
23+
is_ip = False
24+
if not is_ip:
25+
try:
26+
self.host = socket.gethostbyname(self.host)
27+
except Exception as err:
28+
return_error(f"{self.host} is not a valid IP nor does not resolve to an IP - {err}")
29+
30+
def test_connect(self):
31+
try:
32+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
33+
s.connect((self.host, self.port))
34+
s.sendall(b"test")
35+
data = s.recv(1024)
36+
if data.decode().startswith("Response"):
37+
return 'ok'
38+
else:
39+
return "There was an issue. Please check your Arduino code"
40+
except Exception as err:
41+
return_error(err)
42+
43+
def send_data(self, value):
44+
data = None
45+
try:
46+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
47+
s.connect((self.host, self.port))
48+
s.sendall(value.encode())
49+
data = s.recv(1024)
50+
except Exception as err:
51+
return_error(err)
52+
return data
53+
54+
55+
''' HELPER FUNCTIONS '''
56+
57+
''' COMMAND FUNCTIONS '''
58+
59+
60+
def test_module(server: Server) -> str:
61+
return server.test_connect()
62+
63+
64+
def arduino_set_pin_command(server: Server, args: dict) -> CommandResults:
65+
pin_type = args.get('pin_type')
66+
prefix = "Arduino.DigitalPins" if pin_type == "digital" else "Arduino.AnalogPins"
67+
pin_number = args.get('pin_number')
68+
try:
69+
pin_number = int(pin_number) # type: ignore
70+
except Exception as err:
71+
return_error(f"'Pin number' must be a number - {err}")
72+
value = args.get('value')
73+
try:
74+
value = int(value) # type: ignore
75+
except Exception as err:
76+
return_error(f"'Value' must be a number - {err}")
77+
result = int(server.send_data(f"set:{pin_type}:{pin_number},{value}"))
78+
results = [{
79+
"PinType": "Digital" if pin_type == "digital" else "Analog",
80+
"PinNumber": pin_number,
81+
"PinValue": result
82+
}]
83+
command_results = CommandResults(
84+
outputs_prefix=prefix,
85+
outputs_key_field=['PinNumber', 'PinType'],
86+
outputs=results,
87+
readable_output=tableToMarkdown(f"Set pin {pin_number} on {server.host}({server.port}):", results)
88+
)
89+
return command_results
90+
91+
92+
def arduino_get_pin_command(server: Server, args: dict) -> CommandResults:
93+
pin_type = args.get('pin_type')
94+
prefix = "Arduino.DigitalPins" if pin_type == "digital" else "Arduino.AnalogPins"
95+
pin_number = args.get('pin_number')
96+
try:
97+
pin_number = int(pin_number) # type: ignore
98+
except Exception as err:
99+
return_error(f"'Pin number' must be a number - {err}")
100+
result: int = int(server.send_data(f"get:{pin_type}:{pin_number}"))
101+
results = [{
102+
"PinType": "Digital" if pin_type == "digital" else "Analog",
103+
"PinNumber": pin_number,
104+
"PinValue": result
105+
}]
106+
command_results = CommandResults(
107+
outputs_prefix=prefix,
108+
outputs_key_field=['PinNumber', 'PinType'],
109+
outputs=results,
110+
readable_output=tableToMarkdown(f"Get pin {pin_number} on {server.host}({server.port}):", results)
111+
)
112+
return command_results
113+
114+
115+
def arduino_send_data_command(server: Server, args: dict) -> CommandResults:
116+
data = args.get('data')
117+
result = server.send_data(data)
118+
results = [{
119+
"Sent": data,
120+
"Received": result.decode()
121+
}]
122+
command_results = CommandResults(
123+
outputs_prefix="Arduino.DataSend",
124+
outputs_key_field='Sent',
125+
outputs=results,
126+
readable_output=tableToMarkdown(f"Data sent to {server.host}({server.port}):", results)
127+
)
128+
return command_results
129+
130+
131+
''' MAIN FUNCTION '''
132+
133+
134+
def main():
135+
params = demisto.params()
136+
host = params.get('host')
137+
port = params.get('port')
138+
args = demisto.args()
139+
if "host" in args and "port" in args:
140+
host = args.get('host')
141+
port = args.get('port')
142+
try:
143+
port = int(port)
144+
except Exception as err:
145+
return_error(f"'Port' must be a number - {err}")
146+
command: str = demisto.command()
147+
demisto.debug(f'Command being called is {command}')
148+
149+
commands = {
150+
'arduino-set-pin': arduino_set_pin_command,
151+
'arduino-get-pin': arduino_get_pin_command,
152+
'arduino-send-data': arduino_send_data_command
153+
}
154+
155+
# try:
156+
server: Server = Server(host, port)
157+
158+
if demisto.command() == 'test-module':
159+
return_results(test_module(server))
160+
161+
elif command in commands:
162+
return_results(commands[command](server, args))
163+
164+
else:
165+
return_error(f"{command} command not recognised")
166+
167+
# Log exceptions and return errors
168+
# except Exception as e:
169+
# demisto.error(traceback.format_exc()) # print the traceback
170+
# return_error(f'Failed to execute {command} command.\nError:\n{str(e)}')
171+
172+
173+
''' ENTRY POINT '''
174+
175+
if __name__ in ('__main__', '__builtin__', 'builtins'):
176+
main()
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
category: Utilities
2+
commonfields:
3+
id: Arduino
4+
version: -1
5+
configuration:
6+
- additionalinfo: Hostname or IP
7+
display: Hostname or IP
8+
name: host
9+
required: true
10+
type: 0
11+
- additionalinfo: Port number
12+
defaultvalue: "9090"
13+
display: Port number
14+
name: port
15+
required: true
16+
type: 0
17+
description: Connects to and controls an Arduino pin system using the network.
18+
display: Arduino
19+
name: Arduino
20+
script:
21+
commands:
22+
- arguments:
23+
- auto: PREDEFINED
24+
defaultValue: digital
25+
description: The type of pin
26+
name: pin_type
27+
predefined:
28+
- digital
29+
- analog
30+
required: true
31+
- description: The pin number to set
32+
name: pin_number
33+
required: true
34+
- description: The value to set the pin to
35+
name: value
36+
required: true
37+
- description: Host name / IP address (optional - overrides parameters)
38+
name: host
39+
- description: Port number (optional - overrides parameters)
40+
name: port
41+
description: Requests that a pin be set
42+
name: arduino-set-pin
43+
outputs:
44+
- contextPath: Arduino.DigitalPins
45+
description: Digital Pins
46+
- contextPath: Arduino.DigitalPins.PinNumber
47+
description: PinNumber
48+
type: number
49+
- contextPath: Arduino.DigitalPins.PinType
50+
description: Pin Type
51+
type: string
52+
- contextPath: Arduino.DigitalPins.PinValue
53+
description: Pin Value
54+
type: number
55+
- contextPath: Arduino.AnalogPins
56+
description: Analog Pins
57+
- contextPath: Arduino.AnalogPins.PinNumber
58+
description: PinNumber
59+
type: number
60+
- contextPath: Arduino.AnalogPins.PinType
61+
description: Pin Type
62+
type: string
63+
- contextPath: Arduino.AnalogPins.PinValue
64+
description: Pin Value
65+
type: number
66+
- arguments:
67+
- auto: PREDEFINED
68+
defaultValue: digital
69+
description: Pin type
70+
name: pin_type
71+
predefined:
72+
- digital
73+
- analog
74+
required: true
75+
- description: The pin to read the value from
76+
name: pin_number
77+
required: true
78+
- description: Host name / IP address (optional - overrides parameters)
79+
name: host
80+
- description: Port number (optional - overrides parameters)
81+
name: port
82+
description: Requests the value of a pin
83+
name: arduino-get-pin
84+
outputs:
85+
- contextPath: Arduino.DigitalPins
86+
description: Digital Pins
87+
- contextPath: Arduino.DigitalPins.PinNumber
88+
description: PinNumber
89+
type: number
90+
- contextPath: Arduino.DigitalPins.PinType
91+
description: Pin Type
92+
type: string
93+
- contextPath: Arduino.DigitalPins.PinValue
94+
description: Pin Value
95+
type: number
96+
- contextPath: Arduino.AnalogPins
97+
description: Analog Pins
98+
- contextPath: Arduino.AnalogPins.PinNumber
99+
description: PinNumber
100+
type: number
101+
- contextPath: Arduino.AnalogPins.PinType
102+
description: Pin Type
103+
type: string
104+
- contextPath: Arduino.AnalogPins.PinValue
105+
description: Pin Value
106+
type: number
107+
- arguments:
108+
- description: The data to send
109+
name: data
110+
required: true
111+
- description: Host name / IP address (optional - overrides parameters)
112+
name: host
113+
- description: Port number (optional - overrides parameters)
114+
name: port
115+
description: Send arbitrary data to the Arduino
116+
name: arduino-send-data
117+
outputs:
118+
- contextPath: Arduino.DataSend
119+
description: Data Send
120+
- contextPath: Arduino.DataSend.Sent
121+
description: The data sent
122+
type: string
123+
- contextPath: Arduino.DataSend.Received
124+
description: The data received
125+
type: string
126+
dockerimage: demisto/python3:3.9.1.14969
127+
runonce: false
128+
script: ''
129+
subtype: python3
130+
type: python
131+
fromversion: 6.0.0
132+
tests:
133+
- No tests (auto formatted)

0 commit comments

Comments
 (0)