| 13 | # is created, and later used in the FreakWAN main code path in order to |
| 14 | # get the reading from the sensors, encode and send the information. |
| 15 | class Sensor: |
| 16 | def __init__(self,fw,sensor_config): |
| 17 | self.fw = fw |
| 18 | self.config = sensor_config |
| 19 | self.state = "send_sample" |
| 20 | |
| 21 | # We don't want any automatic communication when acting as sensors. |
| 22 | fw.config['quiet'] = True |
| 23 | fw.config['automsg'] = False |
| 24 | |
| 25 | # Add the sensor channel key if needed. |
| 26 | if not self.fw.keychain.has_key(self.config['key_name']): |
| 27 | self.fw.keychain.add_key(self.config['key_name'],self.config['key_secret']) |
| 28 | |
| 29 | # This method is called from FreakWAN main loop in order to |
| 30 | # execute the sensor state machine, that is: send sample, wait |
| 31 | # for reply for some time, then go in deep sleep. |
| 32 | def exec_state_machine(self,tick): |
| 33 | # Send sensor data. After this step, there should be a pending |
| 34 | # message in the TX queue, with the encoded readings of the |
| 35 | # sensor. |
| 36 | if self.state == "send_sample": |
| 37 | print("[sensor] sending sample") |
| 38 | self.send_sample() |
| 39 | self.state = "wait_tx" |
| 40 | |
| 41 | # Once the TX queue is empty, we will wait a bit more in order |
| 42 | # to receive some data: then we will shut down and enter |
| 43 | # in deep sleep. |
| 44 | if self.state == "wait_tx": |
| 45 | if len(self.fw.send_queue) == 0: |
| 46 | print("[sensor] data sent (tx queue is empty)") |
| 47 | # Give it 10 seconds to receive some reply. |
| 48 | self.poweroff_tick = tick + 100 |
| 49 | self.state = "wait_poweroff" |
| 50 | |
| 51 | # Finally shut down if we sent the message and the time to |
| 52 | # receive some command elapsed. |
| 53 | if self.state == "wait_poweroff": |
| 54 | if tick == self.poweroff_tick: |
| 55 | print("[sensor] entering deep sleep") |
| 56 | self.fw.power_off(self.config['period']) |
| 57 | |
| 58 | def send_sample(self): |
| 59 | if self.config['type'] == 'DHT22': |
| 60 | self.send_sample_dht22() |
| 61 | |
| 62 | # This gets a dictionary of sensor data types and readings, and creates |
| 63 | # the payload for the media message. The format used is just of one |
| 64 | # byte reading type followed by the information itself (usually encoded |
| 65 | # as a floating point number, but it is type-specific), so multiple readings |
| 66 | # are sent in a single message. |
| 67 | def encode_data(self,data): |
| 68 | encoded = bytes() |
| 69 | for keytype in data: |
| 70 | encoded += struct.pack("<Bf",keytype,data[keytype]) |
| 71 | return encoded |
| 72 | |