cosmic-pi-deprecated / cosmicpi-daq

Data acquisition package for reading data from an Arduino via USB serial on a Raspberry Pi
6 stars 3 forks source link

Refactored command handling #22

Closed jlsalmon closed 8 years ago

jlsalmon commented 8 years ago

This commit refactors the command handling to listen for commands on a local socket in a separate thread. A separate program, cosmicpi-cli is included to deal with the argument parsing, send the command over the socket and print the results.

This is done to move the code out of the main loop, and to support daemonising the program in the future (in other words, we will eventually need to run it automatically at boot time and in that case we won't be connected to stdin, therefore we wouldn't be able to send commands unless the program listens on a socket)

quixoft commented 8 years ago

Good thing to do. Running the main loop as a daemon and having a separate cli process is cleaner. Typically we might start to think about a web interface. But in the case of the rpi this probably isn't such a great idea. What I would think about is running the cli thread on another host. Either the eventual user would ssh -X on to the rpi, or to check up on what it's doing and run the cli, or run the cli on his pc to talk to the pi. The third is the web page...

jlsalmon commented 8 years ago

Yes, you're right, we could listen for commands on a TCP socket, then you'd be able to use the cli on another host.

As for the web interface, I think it would be a good idea. We talked about it a few times, having a local web interface so you could see your detector status without an internet connection (and other stuff like how many events are queued to be sent, how full your disk is etc.).

It could also eventually be used to set up the wifi connection on boot via an access point (James and I have talked about this before, I think we talked about it with Stefan as well). Although maybe just editing a text file on the SD card would be less hassle.

The good thing about the latest Raspbian is that it exposes itself as raspberrypi.local, so depending on the network setup you can just type that into the browser and don't need to know the IP address.

quixoft commented 8 years ago

Hi Justin, tested and it works. However it would be be nice to be able to choose to have regular status reports, so that those who want to keep an eye on there system can do so easily without having to run the cli over and over. Suggest that the "s" command toggles regular status reporting on the daq thread. Also I am getting this message often .....

[2016-05-23 13:42:53,333] INFO [detector.py 91] Cosmic event:

    Detector......: 4c:e6:76:1c:9c:41
    Sequence......: {'number': 20}
    Barometer.....: {'pressure': '0.0', 'altitude': '0.0', 'temperature': '0.0'}
    Thermometer...: {'temperature': '0.0', 'humidity': '0.0'}
    Location......: {u'latitude': 46.096062, u'altitude': 487.899994, u'longitude': 5.879577}
    Vibration.....: {'count': '0', 'direction': '0'}
    Accelerometer.: {'y': '0.0', 'x': '0.0', 'z': '0.0'}
    Magnetometer..: {'y': '0.0', 'x': '0.0', 'z': '0.0'}
    Timing........: {u'uptime': 209, u'time_string': 114247, u'counter_frequency': 41998682}
    Status........: {u'missed_events': 0, u'temp_status': 0, u'mag_status': 0, u'accel_status': 0, u'baro_status': 0, u'queue_size': 8, u'buffer_error': 0, u'gps_status': 1}
    Event.........: {u'timestamp': 114248.0812622, u'timer_frequency': 41998681, u'event_number': 4, u'ticks': 841676, u'adc': [[1112, 1112, 1110, 1113, 1113, 1112, 1114, 1111], [1113, 1113, 1113, 1115, 1112, 1114, 1110, 1114]]}

[2016-05-23 13:42:53,534] INFO [detector.py 91] Cosmic event:

    Detector......: 4c:e6:76:1c:9c:41
    Sequence......: {'number': 21}
    Barometer.....: {'pressure': '0.0', 'altitude': '0.0', 'temperature': '0.0'}
    Thermometer...: {'temperature': '0.0', 'humidity': '0.0'}
    Location......: {u'latitude': 46.096062, u'altitude': 487.899994, u'longitude': 5.879577}
    Vibration.....: {'count': '0', 'direction': '0'}
    Accelerometer.: {'y': '0.0', 'x': '0.0', 'z': '0.0'}
    Magnetometer..: {'y': '0.0', 'x': '0.0', 'z': '0.0'}
    Timing........: {u'uptime': 209, u'time_string': 114247, u'counter_frequency': 41998682}
    Status........: {u'missed_events': 0, u'temp_status': 0, u'mag_status': 0, u'accel_status': 0, u'baro_status': 0, u'queue_size': 8, u'buffer_error': 0, u'gps_status': 1}
    Event.........: {u'timestamp': 114248.1015428, u'timer_frequency': 41998681, u'event_number': 5, u'ticks': 851760, u'adc': [[1115, 1111, 1120, 1118, 1116, 1111, 1117, 1112], [1111, 1117, 1107, 1114, 1120, 1112, 1114, 1113]]}

[2016-05-23 13:44:12,018] INFO [command_handler.py 40] Received command: v [2016-05-23 13:44:24,162] INFO [command_handler.py 40] Received command: w [2016-05-23 13:44:28,914] INFO [command_handler.py 40] Received command: s [2016-05-23 13:46:21,403] CRITICAL [blocking_connection.py 418] Connection close detected; result=BlockingConnectionOnClosedArgs(connection=<pika.adapters.select_connection.SelectConnection object at 0x7fa4f2ea6610>, reason_code=320, reason_text='Too Many Missed Heartbeats, No reply in 120 seconds') [2016-05-23 13:46:21,403] CRITICAL [blocking_connection.py 418] Connection close detected; result=BlockingConnectionOnClosedArgs(connection=<pika.adapters.select_connection.SelectConnection object at 0x7fa4f2ea6610>, reason_code=320, reason_text='Too Many Missed Heartbeats, No reply in 120 seconds') Exception in thread Thread-1: Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 810, in bootstrap_inner self.run() File "/usr/lib/python2.7/threading.py", line 763, in run self.__target(_self.args, *_self.__kwargs) File "/home/julian/git-pi/cosmicpi-daq/detector.py", line 68, in run self.sio.connection.process_data_events() File "/usr/local/lib/python2.7/dist-packages/pika/adapters/blocking_connection.py", line 650, in process_data_events self._flush_output(timer.is_ready, common_terminator) File "/usr/local/lib/python2.7/dist-packages/pika/adapters/blocking_connection.py", line 420, in _flush_output result.reason_text) ConnectionClosed: (320, 'Too Many Missed Heartbeats, No reply in 120 seconds')

quixoft commented 8 years ago

Also there should be a clean way to restart the daq thread... this is ugly

[2016-05-23 13:49:15,953] INFO [command_handler.py 40] Received command: s [2016-05-23 13:49:21,109] INFO [command_handler.py 40] Received command: s [2016-05-23 13:49:40,371] INFO [command_handler.py 40] Received command: s [2016-05-23 13:49:42,949] INFO [command_handler.py 40] Received command: s q C^C[2016-05-23 13:50:07,625] INFO [detector.py 108] Stopping detector thread [2016-05-23 13:50:07,625] INFO [cosmicpi-daq.py 181] Quitting ... Traceback (most recent call last): File "cosmicpi-daq.py", line 188, in main() File "cosmicpi-daq.py", line 184, in main sio.close() File "/home/julian/git-pi/cosmicpi-daq/sock.py", line 18, in close self.connection.close() File "/usr/local/lib/python2.7/dist-packages/pika/adapters/blocking_connection.py", line 629, in close self._flush_output(self._closed_result.is_ready) File "/usr/local/lib/python2.7/dist-packages/pika/adapters/blocking_connection.py", line 395, in _flush_output raise exceptions.ConnectionClosed() pika.exceptions.ConnectionClosed

jlsalmon commented 8 years ago

Ok, noted, thanks. I'll take a look later and push another PR to address those.

quixoft commented 8 years ago

Well I have been bashing my brains out trying to recover the adafruit breakouts without power on off. The breakout boards do not get a reset line. At first I thought it was the "wire" library, but now it looks more like a glitch on the power puts the breakouts into a state where they can't be reached through the "wire" interface. Other than adding a transistor to control the power to the breakout boards I am having difficulty finding a solution. Even with usb_io the problem still occurs, less often, but I still see it.

So now for each test... I have to do a "ps" to get the process daq ID, then kill -1 that process which is python, upload my sketch, start up the daq thread again and then use the cli to check the status. I feel that I am no longer close to whats going on in the Arduino. So might I suggest that the cli does not exit after one command, that it includes a reset of the daq and a kill of the daq. Also I like to see that its running and that the Arduino isn't jammed, something that happens during tests. So having a nice uptime and status each second makes it more assuring that something is actually running. Another pain is sharing a terminal between the daq and cli threads. The daq thread overwrites the screen with the status which is annoying and forces me to use two windows. I guess debugging the Arduino code is not what a typical user does, not sure who they will be, but the experience is much heavier to perform tests and far less user friendly. Its not having two processes that's the problem here, I am just talking about the user experience of interacting with the system.

jlsalmon commented 8 years ago

Ok, I think I get where you're coming from.

How about this - the CLI becomes interactive, and you can enter multiple commands in a CLI session. New commands are added to close and reopen the USB connection (no need to stop the entire python program as far as I can see).

The status command could have an option to refresh itself once per second until you stop it with ctrl-c.

That way you'd only need to interact with the CLI window and you could ignore the daemon process. Would that work for you?

quixoft commented 8 years ago

Yes yes, super, just what I need. Thanks, just imagine yourself loading loads of yeast sketches on the Arduino and seeing what happens, turn round time for a test should be as short as possible. Sounds like you have understood my needs. It will also be generally a good feature to monitor the Arduino. Thanks