class NanoGateWay: def __init__(self): self.sock = None self.connected = False self.wlan = WLAN(mode=WLAN.STA) self.riders = {} # dictionary of riders # initialize LoRa as a Gateway (with Tx IQ inversion) self.lora = LoRa(tx_iq=True, rx_iq=False) def connect_to_wlan(self): if not self.wlan.isconnected(): # TODO: change for the correct credentials here (ssid and password) self.wlan.connect(ssid='KCOMIoT', auth=(None, '10noCHOSun'), timeout=7000) while not self.wlan.isconnected(): time.sleep_ms(50) def connect_to_server(self): if self.sock: self.sock.close() self.sock = socket.socket() # TCP try: self.sock.connect((TCP_IP, TCP_PORT)) # TODO self.sock.settimeout(1) self.connected = True except Exception: self.sock.close() # just close the socket and try again later print('Socket connect failed, retrying...') time.sleep_ms(500) def send(self, msg): if self.connected and self.sock: try: self.sock.send(msg) except Exception: self.connected = False self.sock.close() self.sock = None def new_rider(self, name, company, badge, bike, eventid, ridetimestamp): rider = Rider(name, company, badge, bike, eventid, ridetimestamp) self.riders[bike] = rider def recv(self): if self.connected and self.sock: try: data = self.sock.recv(1024) except socket.timeout: return None except socket.error as e: if e.args[0] != EAGAIN: self.connected = False return None return data def run(self): data = self.recv() if data: print(data) parsed_json = json.loads(data.decode('ascii')) print(parsed_json) if parsed_json['RideStatus'] == "started": self.new_rider(parsed_json['RiderName'], parsed_json['Company'], parsed_json['BadgeNumber'], parsed_json['BikeID'],parsed_json['EventID'],parsed_json['RideTimestamp']) # start the race print(str({'id':parsed_json['BikeID'], 'cm': 's'})) packet_tx = json.dumps({'id':parsed_json['BikeID'], 'cm': 's'}) print ("packet_tx = " + packet_tx) self.lora.send(packet_tx, True) lora_d = self.lora.recv() if lora_d: parsed_json = json.loads(lora_d.decode('ascii')) print(parsed_json) # update the rider info (if the rider already exists) bike_id = parsed_json['id'] if bike_id in self.riders: self.riders[bike_id].speed = parsed_json['sp'] self.riders[bike_id].distance = parsed_json['ds'] self.riders[bike_id].crank = parsed_json['cr'] if parsed_json['st'] == 'i' or parsed_json['st'] == 'f': self.riders[bike_id].status = 'finished' elif parsed_json['st'] == 'r': self.riders[bike_id].status = 'counting' else: self.riders[bike_id].status = 'started' # Assemble the TCP packet wheel_count=self.riders[bike_id].crank * 7 json_d = {"RiderName":self.riders[bike_id].name, "Company":self.riders[bike_id].company, "BadgeNumber":self.riders[bike_id].badge, \ "EventID":self.riders[bike_id].eventid, "RideTimestamp":'{:f}'.format(self.riders[bike_id].ridetimestamp), "BikeID":bike_id, \ "RideStatus":self.riders[bike_id].status, "RideInfo":[{"CounterTimestamp": float(time.ticks_ms()), \ "CrankCounter":self.riders[bike_id].crank, "WheelCounter":wheel_count}]} json_str = json.dumps(json_d) print("Outgoing from Gateway: " + str(json_str)) self.send(json_str+"\n") if not self.connected: self.connect_to_wlan() self.connect_to_server()
def main(): start_delay_ms = 0 time_ms = time.ticks_ms() last_sent_ms = time_ms state = 'IDLE' # States are: 'IDLE', 'RUNNING', 'FINISHED' Pin('G4', mode=Pin.IN, pull=Pin.PULL_DOWN) crank = PulseCounter('G5', Pin.PULL_DOWN, Pin.IRQ_RISING, 250) # initialize LoRa as a node (with Rx IQ inversion) lora = LoRa(tx_iq=False, rx_iq=True) # LCD pin configuration: lcd_rs = 'G11' lcd_en = 'G12' lcd_d4 = 'G15' lcd_d5 = 'G16' lcd_d6 = 'G13' lcd_d7 = 'G28' lcd_columns = 16 lcd_rows = 1 lcd = LCD.CharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7, lcd_columns, lcd_rows) rider = Rider(lcd) print("Ready for first rider.") lcd.clear() lcd.message("Ready fo\nr first rider.") while True: if state == 'IDLE': packet_rx = lora.recv() if packet_rx: try: parsed_json = json.loads(packet_rx.decode('ascii')) cmd = parsed_json['cm'] id = parsed_json['id'] if cmd == 's' and id == config.id: print('Going to running state') start_delay_ms = ((machine.rng() % 30) * 100) + time.ticks_ms() # send 's' (started) state over LoRa packet_tx = json.dumps({'id': config.id, 'cr':0, 'ds':int(rider.distance()), 'sp':int(rider.avg_speed()), 'st':'s'}) lora.send(packet_tx, True) rider.countdown() crank.counter = 0 # change to the running state and notify the gateway state = 'RUNNING' packet_tx = json.dumps({'id': config.id, 'cr':0, 'ds':int(rider.distance()), 'sp':int(rider.avg_speed()), 'st':'r'}) lora.send(packet_tx, True) except Exception: print('Corrupted LoRa packet') else: time.sleep_ms(50) elif state == 'RUNNING': if rider.ride(crank): print('Going to finished state') state = 'FINISHED' packet_tx = json.dumps({'id': config.id, 'cr':crank.counter, 'ds':int(rider.distance()), 'sp':int(rider.avg_speed()), 'st':'f'}) lora.send(packet_tx, True) time_ms = time.ticks_ms() if time_ms < start_delay_ms: pass elif time_ms > last_sent_ms + LORA_SEND_PERIOD_MS: last_sent_ms = time_ms packet_tx = json.dumps({'id':config.id, 'cr':crank.counter, 'ds':int(rider.distance()), 'sp':int(rider.avg_speed()), 'st':'r'}) print(packet_tx + ' {}'.format(last_sent_ms)) lora.send(packet_tx, True) else: print('attempt to receive lora') packet_rx = lora.recv() if packet_rx: print(packet_rx) try: # I've seen this failing sometimes parsed_json = json.loads(packet_rx.decode('ascii')) # check the packet received and process the commands except Exception: print('Corrupted LoRa packet') time.sleep(1.0 - (((time.ticks_ms() / 1000) - rider.starttime) % 1.0)) else: print('finishing ride') rider.finish() # change to the running state and notify the gateway state = 'IDLE' packet_tx = json.dumps({'id': config.id, 'cr':crank.counter, 'ds':int(rider.distance()), 'sp':int(rider.avg_speed()), 'st':'i'}) lora.send(packet_tx, True) crank.counter = 0