comparison telemetrix_local.py @ 9:7e19dffb767b default tip

rm more unused code and logging
author drewp@bigasterisk.com
date Mon, 06 Feb 2023 11:53:42 -0800
parents 5441581186f8
children
comparison
equal deleted inserted replaced
8:5441581186f8 9:7e19dffb767b
21 # import struct 21 # import struct
22 import sys 22 import sys
23 import time 23 import time
24 import logging 24 import logging
25 log = logging.getLogger('tele') 25 log = logging.getLogger('tele')
26 cmdlog = logging.getLogger('command')
26 27
27 # noinspection PyPackageRequirementscd 28 # noinspection PyPackageRequirementscd
28 from serial.serialutil import SerialException 29 from serial.serialutil import SerialException
29 # noinspection PyPackageRequirements 30 # noinspection PyPackageRequirements
30 from serial.tools import list_ports 31 from serial.tools import list_ports
104 105
105 """ 106 """
106 107
107 # noinspection PyPep8,PyPep8 108 # noinspection PyPep8,PyPep8
108 def __init__(self, com_port=None, 109 def __init__(self, com_port=None,
109 arduino_instance_id=1, arduino_wait=4, 110 arduino_instance_id=1,
110 sleep_tune=0.0001, autostart=True, 111 autostart=True, shutdown_on_exception=True,
111 loop=None, shutdown_on_exception=True,
112 close_loop_on_shutdown=True,
113 ip_address=None, ip_port=31335): 112 ip_address=None, ip_port=31335):
114 113
115 """ 114 """
116 If you have a single Arduino connected to your computer, 115 If you have a single Arduino connected to your computer,
117 then you may accept all the default values. 116 then you may accept all the default values.
120 119
121 :param com_port: e.g. COM3 or /dev/ttyACM0. 120 :param com_port: e.g. COM3 or /dev/ttyACM0.
122 121
123 :param arduino_instance_id: Must match value in the Telemetrix4Arduino sketch 122 :param arduino_instance_id: Must match value in the Telemetrix4Arduino sketch
124 123
125 :param arduino_wait: Amount of time to wait for an Arduino to
126 fully reset itself.
127
128 :param sleep_tune: A tuning parameter (typically not changed by user)
129
130 :param autostart: If you wish to call the start method within 124 :param autostart: If you wish to call the start method within
131 your application, then set this to False. 125 your application, then set this to False.
132
133 :param loop: optional user provided event loop
134 126
135 :param shutdown_on_exception: call shutdown before raising 127 :param shutdown_on_exception: call shutdown before raising
136 a RunTimeError exception, or 128 a RunTimeError exception, or
137 receiving a KeyboardInterrupt exception 129 receiving a KeyboardInterrupt exception
138
139 :param close_loop_on_shutdown: stop and close the event loop loop
140 when a shutdown is called or a serial
141 error occurs
142 130
143 """ 131 """
144 # check to make sure that Python interpreter is version 3.8.3 or greater 132 # check to make sure that Python interpreter is version 3.8.3 or greater
145 python_version = sys.version_info 133 python_version = sys.version_info
146 if python_version[:3] < (3, 8, 3): 134 if python_version[:3] < (3, 8, 3):
148 "required for use of this program.") 136 "required for use of this program.")
149 137
150 # save input parameters 138 # save input parameters
151 self.com_port = com_port 139 self.com_port = com_port
152 self.arduino_instance_id = arduino_instance_id 140 self.arduino_instance_id = arduino_instance_id
153 self.arduino_wait = arduino_wait
154 self.sleep_tune = sleep_tune
155 self.autostart = autostart 141 self.autostart = autostart
156 self.ip_address = ip_address 142 self.ip_address = ip_address
157 self.ip_port = ip_port 143 self.ip_port = ip_port
158 144
159 # if tcp, this variable is set to the connected socket 145 # if tcp, this variable is set to the connected socket
160 self.sock = None 146 self.sock = None
161 147
162 # set the event loop
163 if loop is None:
164 self.loop = asyncio.get_event_loop()
165 else:
166 self.loop = loop
167
168 self.shutdown_on_exception = shutdown_on_exception 148 self.shutdown_on_exception = shutdown_on_exception
169 self.close_loop_on_shutdown = close_loop_on_shutdown
170 149
171 # dictionaries to store the callbacks for each pin 150 # dictionaries to store the callbacks for each pin
172 self.analog_callbacks = {} 151 self.analog_callbacks = {}
173 152
174 self.digital_callbacks = {} 153 self.digital_callbacks = {}
197 self.dht_count = 0 176 self.dht_count = 0
198 177
199 # serial port in use 178 # serial port in use
200 self.serial_port: Optional[TelemetrixAioSerial] = None 179 self.serial_port: Optional[TelemetrixAioSerial] = None
201 180
202 self.the_task = None 181 self.report_task = None
203
204 # flag to indicate we are in shutdown mode
205 self.shutdown_flag = False
206 182
207 # reported features 183 # reported features
208 self.reported_features = 0 184 self.reported_features = 0
209 185
210 # To add a command to the command dispatch table, append here. 186 # To add a command to the command dispatch table, append here.
294 270
295 print(f'TelemetrixAIO Version: {PrivateConstants.TELEMETRIX_AIO_VERSION}') 271 print(f'TelemetrixAIO Version: {PrivateConstants.TELEMETRIX_AIO_VERSION}')
296 print(f'Copyright (c) 2018-2021 Alan Yorinks All rights reserved.\n') 272 print(f'Copyright (c) 2018-2021 Alan Yorinks All rights reserved.\n')
297 273
298 if autostart: 274 if autostart:
299 self.loop.run_until_complete(self.start_aio()) 275 raise NotImplementedError("you run start_aio")
300 276
301 async def start_aio(self): 277 async def start_aio(self):
302 """ 278 """
303 This method may be called directly, if the autostart 279 This method may be called directly, if the autostart
304 parameter in __init__ is set to false. 280 parameter in __init__ is set to false.
335 if self.shutdown_on_exception: 311 if self.shutdown_on_exception:
336 await self.shutdown() 312 await self.shutdown()
337 raise RuntimeError('No Arduino Found or User Aborted Program') 313 raise RuntimeError('No Arduino Found or User Aborted Program')
338 # using tcp/ip 314 # using tcp/ip
339 else: 315 else:
340 self.sock = TelemetrixAioSocket(self.ip_address, self.ip_port, self.loop) 316 self.sock = TelemetrixAioSocket(self.ip_address, self.ip_port)
341 await self.sock.start() 317 await self.sock.start()
342 # self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 318 # self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
343 # self.sock.connect((self.ip_address, self.ip_port)) 319 # self.sock.connect((self.ip_address, self.ip_port))
344 # print(f'Successfully connected to: {self.ip_address}:{self.ip_port}') 320 # print(f'Successfully connected to: {self.ip_address}:{self.ip_port}')
345 321
346 # get arduino firmware version and print it 322 # get arduino firmware version and print it
347 firmware_version = await self._get_firmware_version() 323 firmware_version = await self._get_firmware_version()
348 log.debug(f'start_aio p2 {firmware_version=}')
349 if not firmware_version: 324 if not firmware_version:
350 log.info('*** Firmware Version retrieval timed out. ***') 325 log.info('*** Firmware Version retrieval timed out. ***')
351 log.info('\nDo you have Arduino connectivity and do you have the ') 326 log.info('\nDo you have Arduino connectivity and do you have the ')
352 log.info('Telemetrix4Arduino sketch uploaded to the board and are connected') 327 log.info('Telemetrix4Arduino sketch uploaded to the board and are connected')
353 log.info('to the correct serial port.\n') 328 log.info('to the correct serial port.\n')
355 '"list_serial_ports" in your console.') 330 '"list_serial_ports" in your console.')
356 if self.shutdown_on_exception: 331 if self.shutdown_on_exception:
357 await self.shutdown() 332 await self.shutdown()
358 raise RuntimeError 333 raise RuntimeError
359 else: 334 else:
360 log.debug(f'p3')
361 if firmware_version[1] < 5: 335 if firmware_version[1] < 5:
362 raise RuntimeError('Please upgrade the server firmware to version 5.0.0 or greater') 336 raise RuntimeError('Please upgrade the server firmware to version 5.0.0 or greater')
363 log.info(f'Telemetrix4Arduino Version Number: {firmware_version[1]}.' 337 log.info(f'Telemetrix4Arduino Version Number: {firmware_version[1]}.'
364 f'{firmware_version[2]}.{firmware_version[3]}') 338 f'{firmware_version[2]}.{firmware_version[3]}')
365 # start the command dispatcher loop 339 # start the command dispatcher loop
366 command = [PrivateConstants.ENABLE_ALL_REPORTS] 340 command = [PrivateConstants.ENABLE_ALL_REPORTS]
367 log.debug('start_aio send ENABLE_ALL_REPORTS')
368 await self._send_command(command) 341 await self._send_command(command)
369 if not self.loop: 342 self.report_task = asyncio.create_task(self._arduino_report_dispatcher())
370 log.debug('start_aio new loop') 343 log.debug(f'create task for _arduino_report_dispatcher done: {self.report_task}')
371 self.loop = asyncio.get_event_loop()
372 self.the_task = self.loop.create_task(self._arduino_report_dispatcher())
373 log.debug('create task for _arduino_report_dispatcher')
374 log.debug(f'create task for _arduino_report_dispatcher done: {self.the_task}')
375 344
376 # get the features list 345 # get the features list
377 command = [PrivateConstants.GET_FEATURES] 346 command = [PrivateConstants.GET_FEATURES]
378 log.debug('send get_features')
379 await self._send_command(command) 347 await self._send_command(command)
380 # time.sleep(.5) 348 # time.sleep(.5)
381 349
382 # Have the server reset its data structures 350 # Have the server reset its data structures
383 command = [PrivateConstants.RESET] 351 command = [PrivateConstants.RESET]
384 log.debug('send reset')
385 await self._send_command(command) 352 await self._send_command(command)
386 log.debug(f'start_aio bye\n')
387
388 async def get_event_loop(self):
389 """
390 Return the currently active asyncio event loop
391
392 :return: Active event loop
393
394 """
395 return self.loop
396 353
397 async def _find_arduino(self): 354 async def _find_arduino(self):
398 """ 355 """
399 This method will search all potential serial ports for an Arduino 356 This method will search all potential serial ports for an Arduino
400 containing a sketch that has a matching arduino_instance_id as 357 containing a sketch that has a matching arduino_instance_id as
421 serial_ports.append(self.serial_port) 378 serial_ports.append(self.serial_port)
422 379
423 # display to the user 380 # display to the user
424 print('\t' + port.device) 381 print('\t' + port.device)
425 382
426 # wait for arduino to reset
427 print('\nWaiting {} seconds(arduino_wait) for Arduino devices to '
428 'reset...'.format(self.arduino_wait))
429 await asyncio.sleep(self.arduino_wait)
430
431 print('\nSearching for an Arduino configured with an arduino_instance = ', 383 print('\nSearching for an Arduino configured with an arduino_instance = ',
432 self.arduino_instance_id) 384 self.arduino_instance_id)
433 385
434 for serial_port in serial_ports: 386 for serial_port in serial_ports:
435 self.serial_port = serial_port 387 self.serial_port = serial_port
455 log.info(f'Searching for correct arduino_instance_id: {self.arduino_instance_id}') 407 log.info(f'Searching for correct arduino_instance_id: {self.arduino_instance_id}')
456 while True: 408 while True:
457 # if port is not found, a serial exception will be thrown 409 # if port is not found, a serial exception will be thrown
458 log.info('Opening {} ...'.format(self.com_port)) 410 log.info('Opening {} ...'.format(self.com_port))
459 self.serial_port = TelemetrixAioSerial(self.com_port, 115200) 411 self.serial_port = TelemetrixAioSerial(self.com_port, 115200)
460 # log.debug('await open')
461 await self.serial_port.open() 412 await self.serial_port.open()
462 413
463 # print('Waiting {} seconds for the Arduino To Reset.'
464 # .format(self.arduino_wait))
465 # await asyncio.sleep(self.arduino_wait)
466 command = [PrivateConstants.ARE_U_THERE] 414 command = [PrivateConstants.ARE_U_THERE]
467 try: 415 try:
468 i_am_here = await asyncio.wait_for(self._send_command(command, has_response=True), timeout=0.5) 416 i_am_here = await asyncio.wait_for(self._send_command(command, has_response=True), timeout=0.5)
469 except asyncio.TimeoutError: 417 except asyncio.TimeoutError:
470 log.info(f'no answer- retrying') 418 log.info(f'no answer- retrying')
481 This method retrieves the Arduino4Telemetrix firmware version 429 This method retrieves the Arduino4Telemetrix firmware version
482 430
483 :returns: Firmata firmware version 431 :returns: Firmata firmware version
484 """ 432 """
485 command = [PrivateConstants.GET_FIRMWARE_VERSION] 433 command = [PrivateConstants.GET_FIRMWARE_VERSION]
486 log.debug('GET_FIRMWARE_VERSION')
487 firmware_version = await self._send_command(command, has_response=True) 434 firmware_version = await self._send_command(command, has_response=True)
488 log.debug(f'{firmware_version=}\n')
489
490 return firmware_version 435 return firmware_version
491 436
492 async def analog_write(self, pin, value): 437 async def analog_write(self, pin, value):
493 """ 438 """
494 Set the specified pin to the specified value. 439 Set the specified pin to the specified value.
2054 """ 1999 """
2055 This method attempts an orderly shutdown 2000 This method attempts an orderly shutdown
2056 If any exceptions are thrown, they are ignored. 2001 If any exceptions are thrown, they are ignored.
2057 2002
2058 """ 2003 """
2059 self.shutdown_flag = True
2060 # stop all reporting - both analog and digital 2004 # stop all reporting - both analog and digital
2061 try: 2005 try:
2062 if self.serial_port: 2006 if self.serial_port:
2063 command = [PrivateConstants.STOP_ALL_REPORTS] 2007 command = [PrivateConstants.STOP_ALL_REPORTS]
2064 await self._send_command(command) 2008 await self._send_command(command)
2065
2066 time.sleep(.5)
2067
2068 if self.close_loop_on_shutdown:
2069 self.loop.stop()
2070 elif self.sock: 2009 elif self.sock:
2071 command = [PrivateConstants.STOP_ALL_REPORTS] 2010 command = [PrivateConstants.STOP_ALL_REPORTS]
2072 await self._send_command(command) 2011 await self._send_command(command)
2073 self.the_task.cancel() 2012 self.report_task.cancel()
2074 time.sleep(.5)
2075 if self.close_loop_on_shutdown:
2076 self.loop.stop()
2077 except (RuntimeError, SerialException): 2013 except (RuntimeError, SerialException):
2078 pass 2014 pass
2079 2015
2080 async def disable_all_reporting(self): 2016 async def disable_all_reporting(self):
2081 """ 2017 """
2476 if command: 2412 if command:
2477 # the length of the list is added at the head 2413 # the length of the list is added at the head
2478 command.insert(0, len(command)) 2414 command.insert(0, len(command))
2479 # print(command) 2415 # print(command)
2480 send_message = bytes(command) 2416 send_message = bytes(command)
2481 log.debug(f'sending {CommandName[command[1]]} {command[2:]}') 2417 cmdlog.debug(f'sending {CommandName[command[1]]} {command[2:]}')
2482 if not self.ip_address: 2418 if not self.ip_address:
2483 await self.serial_port.write(send_message) 2419 await self.serial_port.write(send_message)
2484 else: 2420 else:
2485 await self.sock.write(send_message) 2421 await self.sock.write(send_message)
2486 # await asyncio.sleep(.1) 2422 # await asyncio.sleep(.1)
2489 return None 2425 return None
2490 else: 2426 else:
2491 header = await self.serial_port.read(1) 2427 header = await self.serial_port.read(1)
2492 packet_length = header[0] 2428 packet_length = header[0]
2493 pkt = await self.serial_port.read(packet_length) 2429 pkt = await self.serial_port.read(packet_length)
2494 log.debug(f'got response {list(pkt)}') 2430 cmdlog.debug(f'got response {list(pkt)}')
2495 2431
2496 return pkt 2432 return pkt