def run(self): t_next = skibase.get_time_millis() + KFNET_PACKET_TIMEOUT_MS while not self._got_stop_event(): # Send to network (from queue) while self._queue.empty() is False: packet = self._queue.get() self._send(packet) # relay back the task that was sent. # The main program will wait for the task to be relayed # back before acting. # Add delay before relaying self._main_queue.put(skibase.TASK_DELAY_MS + 12) self._main_queue.put(packet.task) self._queue.task_done() # Receive from network (to queue) packet = self._receive() # blocking if packet is not None: self._main_queue.put(packet.task) # Check if p_to for p_id is timed out (once every X ms) t_now = skibase.get_time_millis() if t_now > t_next: for [p_to, p_id] in self._known_packet_ids[:]: if p_to < t_now: skibase.log_debug( ("Removing packet ID '%s' with timeout %d.") \ % (p_id.decode(), p_to)) self._known_packet_ids.remove([p_to, p_id]) t_next = t_next + 1000 # Empty queue and stop while self._queue.empty() is False: self._queue.get() self._queue.task_done()
def test(): skibase.set_time_start() # Arguments parser = argparse.ArgumentParser(description=__doc__) parser = skibase.args_add_log(parser) parser = args_add_kfnet(parser) args = parser.parse_args() # Parse skibase.log_config(args.loglevel.upper(), args.syslog) # Signal skibase.signal_setup([signal.SIGINT, signal.SIGTERM]) # Start queue main_queue = queue.Queue() # Start kfnet kfnet_obj = kfnet_start(main_queue, args.interface, MCAST_GRP, args.ip_addr, args.mcast_port) # Loop (main) skibase.log_notice("Running Kesselfall network unittest") counter = random.randint(0, 0xFF) t_next_send = skibase.get_time_millis() while not skibase.signal_counter and kfnet_obj.status(): try: task = main_queue.get(block=True, timeout=0.25) except queue.Empty: task = None if task: try: skibase.log_notice("-> task: %s" % skibase.task_to_str(task)) except: skibase.log_warning("kfnet got unknown task") main_queue.task_done() if t_next_send < skibase.get_time_millis(): # Send packet to kfnet task # otherwise use kfnet_obj.queue_task(task) packet = kfnet_obj.create_packet() packet.task = skibase.TASK_PROGRAM + \ (counter & skibase.MINOR_TASK) kfnet_obj.queue_packet(packet) skibase.log_notice("<- Packet: %s :: task: %s" %\ (packet.id.decode(), task_to_str(packet.task))) t_next_send = t_next_send \ + random.randint(CHANGE_RATE_MIN, CHANGE_RATE_MAX) counter += 1 kfnet_obj = kfnet_stop(kfnet_obj) skibase.log_notice("Kesselfall network unittest ended")
def _receive(self): data = self.mcast_listener_obj.mcast_check_receive() if data is not None: # On an ad-hoc mesh network we will probably receive the # same packet multiple times. We will only store each # packet (packet ID) for a short time, and then discard # it in case of an "rereceived" packet. packet = KesselfallHeader.from_buffer_copy(data) # Check if packet was sent by ourselves if packet.src == self.source_id: return None # Check packet is valid if packet.stx != KFNET_STX or packet.etx != KFNET_ETX: skibase.log_warning(("Invalid packet: \n%s") \ %(bytes_to_hex_str(data))) return None t_timeout = skibase.get_time_millis() + KFNET_PACKET_TIMEOUT_MS for i, [p_to, p_id] in enumerate(self._known_packet_ids[:]): # Check if this packet was already received. if packet.id == p_id: # Renew timeout skibase.log_debug( "Renewing timout of packet ID '%s' from %d to %d." \ % (packet.id.decode(), p_to, t_timeout)) self._known_packet_ids[i] = [t_timeout, p_id] return None # We have identified a new packet # Send packet and add it to the list of _known_packet_ids self._send(packet) # Prioritize send skibase.log_info( "Received packet '%s' with timeout: %d." \ % (packet.id.decode(), t_timeout)) self._known_packet_ids.append([t_timeout, packet.id]) return packet return None
def loop(main_queue, program_id, kfnet_obj, butt_obj, sphat_obj, ws281x_obj, dbgled_obj): next_kick = 0 program_can_change_again = 0 while not skibase.signal_counter \ and kfnet_obj.status() \ and butt_obj.status() \ and sphat_obj.status() \ and ws281x_obj.status() \ and dbgled_obj.status(): next_kick = wd.wd_check(next_kick) try: task = main_queue.get(block=True, timeout=LOOP_SPEED) except queue.Empty: task = None if task: if task == skibase.TASK_BUTTON_PRESS: now = skibase.get_time_millis() if now >= program_can_change_again: program_id = get_next_program(program_id) # Add program_id to kfnet as a task that is transmitted # Do not execute task yet, but wait for kfnet to relay # the task back when it is sent. This should make the # network appear more "in sync". kfnet_obj.queue_task(skibase.TASK_PROGRAM + program_id) skibase.log_info("task: press: %s" % \ program_id_to_str(program_id)) program_can_change_again = now + PROGRAM_CHANGE_BLOCK_MS else: skibase.log_info("Ignoring program change.") elif task == skibase.TASK_BUTTON_LONG_1: skibase.log_info("task: long press") ws281x_obj.program = 0xff sphat_obj.program = 0xff dbgled_obj.program = 0xff elif task == skibase.TASK_BUTTON_LONG_2: do_shutdown() main_queue.task_done() break elif (task & skibase.MAJOR_TASK) == skibase.TASK_DELAY_MS: skibase.log_info("task: delay") do_delay_task(task) elif (task & skibase.MAJOR_TASK) == skibase.TASK_PROGRAM: program_id = get_program_from_task(task) ws281x_obj.program = program_id sphat_obj.program = program_id dbgled_obj.program = program_id skibase.log_notice("task: program: %s" % \ program_id_to_str(program_id)) else: skibase.log_warning("skipi got unknown task!") try: skibase.log_warning("task: %s" % task_to_str(task)) except: skibase.log_warning("log task failed...") print(task) main_queue.task_done()
def create_packet(self): # Fill packet with default stuff packet = KesselfallHeader() packet.stx = KFNET_STX packet.id = generate_packet_id().encode() packet.src = self.source_id packet.ttl = KFNET_TTL_RETRANS packet.rp = KFNET_RETRANS_PROBABILITY packet.etx = KFNET_ETX # Add packet to _known_packet_ids t_timeout = skibase.get_time_millis() + KFNET_PACKET_TIMEOUT_MS self._known_packet_ids.append([t_timeout, packet.id]) return packet
def run(self): button = gpiozero.Button(BUTT_PIN, pull_up=True) while not self._got_stop_event(): button.wait_for_press(timeout=0.500) if not button.is_pressed: continue t_press = skibase.get_time_millis() button.wait_for_release(timeout=(LONG_PRESS_TIME+10)/1000) t_release = skibase.get_time_millis() press_time = t_release - t_press if press_time >= LONG_PRESS_TIME: skibase.log_debug("Button Long press") self._main_queue.put(skibase.TASK_BUTTON_LONG_1) if button.is_pressed: button.wait_for_release(timeout=None) self._main_queue.put(skibase.TASK_BUTTON_LONG_2) else: self._main_queue.put(skibase.TASK_BUTTON_PRESS) skibase.log_debug("Button Press")
def wd_check(next_kick): time_ms = skibase.get_time_millis() if time_ms >= next_kick or next_kick == 0: wd_kick() next_kick = time_ms + (WD_INTERVAL_SEC * 1000) - WD_GUARD_TIME_MS return next_kick