Пример #1
0
class Plan():
    border_distance = 200

    def __init__(self) -> None:
        self.logging = Logging("events")
        self.display = DisplayBlock()
        self.rgb = RgbLedBlock()
        self.rgb.set_on()

        self.distance_block = DistanceBlock(measurement_period=0.05)
        self.smooth_distance = SmoothedVariable(3, SmoothingType.progressive,
                                                self.distance_block.value)
        self.short_distance_event = self.smooth_distance.less_than(
            self.border_distance, True, self.short_distance)
        self.smooth_distance.more_than(self.border_distance, True,
                                       self.long_distance)
        self.power_save_state = 0

        Planner.repeat(0.5, self.get_distance)

    def short_distance(self):
        self.logging.info("short_distance")
        self.rgb.set_color(RgbLedBlockColor.red)

    def long_distance(self):
        self.logging.info("long_distance")
        self.rgb.set_color(RgbLedBlockColor.green)

    def get_distance(self):
        raw_distance = self.distance_block.value.get(False)
        self.display.clean()
        self.display.print_text(0, 0, str(raw_distance))
        self.display.print_text(0, 9, str(int(self.smooth_distance.get())))
        self.display.showtime()
Пример #2
0
class Plan():
    def __init__(self) -> None:
        self.logging = Logging("events")
        self.rgb = RgbLedBlock()

        self.ir_block = IrBlock()
        self.ir_block.add_remote(IrNumericRemote())

        #to demonstrate equal to
        self.ir_block.value.equal_to(RemoteKey("0"), True, self.light_off)
        Ble.value_remote.equal_to(RemoteKey("0"), True, self.light_off)
        #to demonstrate changed
        self.ir_block.value.updated(True, self.changed, self.ir_block.value)
        Ble.value_remote.updated(True, self.changed, Ble.value_remote)

    def changed(self, active_value):
        value = active_value.get()
        if value and value.name.isdigit():
            key_number = int(value.name)
            if key_number > 0 and key_number < 10:
                self.rgb.set_color_by_id(key_number)
                self.logging.info("set color with id:%d", key_number)

    def light_off(self):
        self.rgb.set_off()
        self.logging.info("light turned off")
Пример #3
0
 def __init__(self, dim_x, dim_y) -> None:
     self.logging = Logging("map")
     self.map_layers = []
     self.current_x = 0
     self.dim_x = dim_x
     self.dim_y = dim_y
     self.removed_count = 0
     self.init()
Пример #4
0
    def init(cls) -> None:
        PowerMgmt.register_management_change_callback(
            cls._set_power_save_timeouts)
        cls._set_power_save_timeouts(
            PowerMgmt.get_plan())  # to be set defaults
        Planner.plan(cls._check_time_to_power_save, True)

        Logging.add_logger(BleLogger)
        cls._start_ble(
        )  #to be allocated big blocks in the beginning it should prevent memory fragmentation
        cls.just_initialized = True
Пример #5
0
  def __init__(self) -> None:
    self.logging = Logging("events")
    self.chassis = Chassis(0x20, 0x21)

    Ble.value_remote.equal_to(RemoteKey("a"), True, self.turn_left)
    Ble.value_remote.equal_to(RemoteKey("d"), True, self.turn_right)
    Ble.value_remote.equal_to(RemoteKey("w"), True, self.speed_up)
    Ble.value_remote.equal_to(RemoteKey("s"), True, self.slow_down)
    Ble.value_remote.equal_to(RemoteKey("z"), True, self.stop)
    Ble.value_remote.equal_to(RemoteKey("x"), True, self.reverse)

    Planner.repeat(1, self.print_power_info)
Пример #6
0
    def __init__(self) -> None:
        self.logging = Logging("events")
        self.rgb = RgbLedBlock()

        self.ir_block = IrBlock()
        self.ir_block.add_remote(IrNumericRemote())

        #to demonstrate equal to
        self.ir_block.value.equal_to(RemoteKey("0"), True, self.light_off)
        Ble.value_remote.equal_to(RemoteKey("0"), True, self.light_off)
        #to demonstrate changed
        self.ir_block.value.updated(True, self.changed, self.ir_block.value)
        Ble.value_remote.updated(True, self.changed, Ble.value_remote)
Пример #7
0
class Plan:
    def __init__(self) -> None:
        self.button = ButtonBlock(measurement_period=0.1)
        self.led = RgbLedBlock()
        self.logging = Logging()
        self.button.value.changed(True, self._button_state_changed)

    def _button_state_changed(self):
        if self.button.value.get():
            self.led.set_on()
            self.logging.info("button pressed")
        else:
            self.led.set_off()
            self.logging.info("button released")
Пример #8
0
    def __init__(self) -> None:
        self.logging = Logging("events")
        self.chassis = Chassis(power_measurement_period=0.3)
        self.rgb = RgbLedBlock()
        self.display = DisplayBlock()
        self.distance = DistanceBlock(measurement_period=0.1)
        self.button = ButtonBlock(measurement_period=0.1)
        self.ir_block = IrBlock()
        self.ir_block.add_remote(IrNumericRemote())

        self.button.value.equal_to(True, True, self.change_patrol)

        self.near_barrier_event = None
        self.far_bariier_event = None
        self.enough_space_event = None
        self.open_space_event = None
        self.patrol = False

        self.display.contrast(0)
        Ble.value_remote.equal_to(RemoteKey("a"), True, self.turn_left)
        Ble.value_remote.equal_to(RemoteKey("d"), True, self.turn_right)
        Ble.value_remote.equal_to(RemoteKey("w"), True, self.speed_up)
        Ble.value_remote.equal_to(RemoteKey("s"), True, self.slow_down)
        Ble.value_remote.equal_to(RemoteKey("z"), True, self.stop)
        Ble.value_remote.equal_to(RemoteKey("x"), True, self.reverse)
        Ble.value_remote.equal_to(RemoteKey("p"), True, self.change_patrol)

        self.ir_block.value.equal_to(IrNumericRemote.key_left, True,
                                     self.turn_left)
        self.ir_block.value.equal_to(IrNumericRemote.key_right, True,
                                     self.turn_right)
        self.ir_block.value.equal_to(IrNumericRemote.key_top, True,
                                     self.speed_up)
        self.ir_block.value.equal_to(IrNumericRemote.key_bottom, True,
                                     self.slow_down)
        self.ir_block.value.equal_to(IrNumericRemote.key_ok, True, self.stop)
        self.ir_block.value.equal_to(IrNumericRemote.key_hash, True,
                                     self.reverse)
        self.ir_block.value.equal_to(IrNumericRemote.key_star, True,
                                     self.change_patrol)

        self.counter = 0
        Planner.repeat(0.5, self.print_power_info)
        PowerMgmt.set_plan(PowerPlan.get_max_performance_plan())

        self.current_smoother = SmoothedVariable(
            3, SmoothingType.average, self.chassis.power.battery_current_mA)
        self.current_smoother.more_than(600, True, self.stop_for_a_while, 1)
        self.heart_beat = False
Пример #9
0
    def __init__(self):
        self.started = False
        self.display = DisplayBlock()
        self.logging = Logging("plan")
        self.button = ButtonBlock()
        self.rgb = RgbLedBlock()
        self.led_default()
        self.dim_x, self.dim_y = self.display.get_dimensions()
        self.center_x = int(self.dim_x / 2)
        self.center_y = int(self.dim_y / 2)
        self.point = None
        self.map = None
        self.score = 0

        self.wait_for_start()
        self.redraw()
Пример #10
0
    def __init__(self) -> None:
        self.logging = Logging("events")
        self.display = DisplayBlock()
        self.rgb = RgbLedBlock()
        self.rgb.set_on()

        self.distance_block = DistanceBlock(measurement_period=0.05)
        self.smooth_distance = SmoothedVariable(3, SmoothingType.progressive,
                                                self.distance_block.value)
        self.short_distance_event = self.smooth_distance.less_than(
            self.border_distance, True, self.short_distance)
        self.smooth_distance.more_than(self.border_distance, True,
                                       self.long_distance)
        self.power_save_state = 0

        Planner.repeat(0.5, self.get_distance)
Пример #11
0
class Plan():
  def __init__(self) -> None:
    self.logging = Logging("events")
    self.chassis = Chassis(0x20, 0x21)

    Ble.value_remote.equal_to(RemoteKey("a"), True, self.turn_left)
    Ble.value_remote.equal_to(RemoteKey("d"), True, self.turn_right)
    Ble.value_remote.equal_to(RemoteKey("w"), True, self.speed_up)
    Ble.value_remote.equal_to(RemoteKey("s"), True, self.slow_down)
    Ble.value_remote.equal_to(RemoteKey("z"), True, self.stop)
    Ble.value_remote.equal_to(RemoteKey("x"), True, self.reverse)

    Planner.repeat(1, self.print_power_info)

  def print_power_info(self):
    voltage = self.chassis.power.battery_voltage_V.get()
    current = self.chassis.power.battery_current_mA.get()
    self.logging.info("battery voltage: {0}, current: {1}".format(voltage, current))

  def slow_down(self):
    self.chassis.set_speed(self.chassis.speed - 1)

  def speed_up(self):
    self.chassis.set_speed(self.chassis.speed + 1)

  def turn_left(self):
    self.chassis.set_manoeuver(self.chassis.manoeuver - 1)

  def turn_right(self):
    self.chassis.set_manoeuver(self.chassis.manoeuver + 1)

  def pressed_l(self):
    self.chassis.set_direction(self.chassis.direction - 1)

  def reverse(self):
    self.logging.info(self.chassis.direction == Direction.forward)
    self.chassis.set_direction(Direction.backward if self.chassis.direction == Direction.forward else Direction.forward)

  def stop(self):
    self.chassis.set_speed(Speed.stop)
    self.chassis.set_manoeuver(Manoeuver.straight)
Пример #12
0
 def __init__(self,
              address_driver_front=0x20,
              address_driver_rear=0x21,
              addr_power=None,
              power_measurement_period=1):
     self.speed = Speed.stop
     self.manoeuver = Manoeuver.straight
     self.direction = Direction.forward
     self.logging = Logging("chassis")
     self.power = PowerBlock(addr_power, power_measurement_period)
     self.front_driver = MotorDriverBlock(address_driver_front)
     self.rear_driver = MotorDriverBlock(address_driver_rear)
Пример #13
0
    def __init__(self, block_type: BlockType, address: int):
        self.type_id = block_type.id
        self.address = address if address else block_type.id  #default block i2c address is equal to its block type

        self.block_type_valid = False
        self.logging = Logging(block_type.name.decode("utf-8"))
        self.block_version = self._get_block_version()

        self.power_save_level = PowerSaveLevel.NoPowerSave
        self._tiny_write_base_id(_power_save_command,
                                 self.power_save_level.to_bytes(1, 'big'),
                                 True)  #wake up block functionality

        if not self.block_version:
            self.logging.warning("module with address 0x%x is not available",
                                 self.address)
        elif self.block_version[0] != self.type_id:
            self.logging.error(
                "unexpected block type. expected: %d, returned: %d",
                self.type_id, self.block_version[0])
        else:
            self.block_type_valid = True
Пример #14
0
def plan():
    logging = Logging()

    display = DisplayBlock()
    dim_x, dim_y = display.get_dimensions()

    logging.info("resolution x: %d, y: %d" % (dim_x, dim_y))
    display.draw_ellipse(int(dim_x / 2), int(dim_y / 2),
                         int(dim_x / 2) - 5,
                         int(dim_y / 2) - 5)

    text = "Hallo"
    letter_width = 8
    letter_height = 8

    text_x = int(dim_x / 2) - int(len(text) * letter_width / 2) + 1
    text_y = int(dim_y / 2) - int(letter_height / 2) - 1

    display.print_text(text_x, text_y, text)
    line_y = text_y + letter_height + 2
    display.draw_line(text_x, line_y, text_x + len(text) * letter_width - 2,
                      line_y)

    display.showtime()
Пример #15
0
class ActiveVariable():
  logging = Logging("act_var")
  def __init__(self, initial_value=None, renew_period:float=0, renew_func=None):
    """
    @param initial_value: if is set Active variable will be preset to this value
    @param renew_period: renew_func will be called with this period if this value > 0
    @param renew_func: this method will be called periodically if renew_period is > 0 or if get is called with the parameter "force"
    """
    self._old_value = initial_value
    self._value = initial_value
    self._renew_period = renew_period
    self._renew_func = renew_func
    self._renew_handle = None
    self._listeners = list()
    self._handle_count = 0

  def change_period(self, new_period):
    self._renew_period = new_period
    if self._renew_handle:
      Planner.kill_task(self._renew_handle)
      self._renew_handle = None
    if self._renew_period > 0:
      self._renew_handle = Planner.repeat(self._renew_period, self._update_value)

  def set(self, value):
    if value is None:
      return #nothing to compare
    self._old_value = self._value
    self._value = value
    for listener in self._listeners:
      _type = listener[1]
      repeat = listener[2]

      if _type == Conditions.equal_to:
        if isinstance(value, float) or isinstance(listener[3], float):
          if (self._old_value is None or not math.isclose(self._old_value, listener[3])) and math.isclose(value, listener[3]):
            if  not repeat:
              self._remove_listener(listener) #TODO: maybe it can be returned to the end of this method it should not be important for the called methd that it will be removed later - events are synchronous
            listener[4](*listener[5], **listener[6])
        else:
          if (self._old_value is None or self._old_value != listener[3]) and value == listener[3]:
            if  not repeat:
              self._remove_listener(listener)
            listener[4](*listener[5], **listener[6])
      elif _type == Conditions.not_equal_to:
        if isinstance(value, float) or isinstance(listener[3], float):
          if (self._old_value is None or math.isclose(self._old_value, listener[3])) and not math.isclose(value, listener[3]):
            if  not repeat:
              self._remove_listener(listener)
            listener[4](*listener[5], **listener[6])
        else:
          if (self._old_value is None or self._old_value == listener[3]) and value != listener[3]:
            if  not repeat:
              self._remove_listener(listener)
            listener[4](*listener[5], **listener[6])
      elif _type == Conditions.less_than:
        if (self._old_value is None or self._old_value >= listener[3]) and value < listener[3]:
          if  not repeat:
            self._remove_listener(listener)
          listener[4](*listener[5], **listener[6])
      elif _type == Conditions.more_than:
        if (self._old_value is None or self._old_value <= listener[3]) and value > listener[3]:
          if  not repeat:
            self._remove_listener(listener)
          listener[4](*listener[5], **listener[6])
      elif _type == Conditions.in_range:
        if (self._old_value is None or self._old_value < listener[3] or self._old_value >= listener[4]) and  value >= listener[3] and value < listener[4]:
          if  not repeat:
            self._remove_listener(listener)
          listener[5](*listener[6], **listener[7])
      elif _type == Conditions.out_of_range:
        if (self._old_value is None or self._old_value >= listener[3] and self._old_value < listener[4]) and (value < listener[3] or value >= listener[4]):
          if  not repeat:
            self._remove_listener(listener)
          listener[5](*listener[6], **listener[7])
      elif _type == Conditions.value_changed:
        if value != self._old_value:
          if  not repeat:
            self._remove_listener(listener)
          listener[3](*listener[4], **listener[5])
      elif _type == Conditions.value_updated:
        if  not repeat:
          self._remove_listener(listener)
        listener[3](*listener[4], **listener[5])
      else:
        self.logging.error("unknown listener type %s" % str(listener[1]))

  def get(self, force=False):
    if force:
      self._update_value()
    return self._value

  def get_previous_value(self):
    return self._old_value

  def _update_value(self):
    if self._renew_func:
      self.set(self._renew_func())

  def _add_listener(self, listener):
    if not self._listeners and self._renew_period > 0:
      self._renew_handle = Planner.repeat(self._renew_period, self._update_value)
    self._listeners.append(listener)
    self._handle_count += 1
    return listener[0] #returns provided handle

  def remove_trigger(self, handle):
    for listener in self._listeners:
      if listener[0] == handle:
        self._listeners.remove(listener)
        if not self._listeners:
          Planner.kill_task(self._renew_handle)
          self._renew_handle = None
        return True
    return False

  def _remove_listener(self, listener):
    return self.remove_trigger(listener[0])

  def equal_to(self, expected, repetitive: bool, function: callable, *args, **kwargs):
    """
    provided function with arguments will be called when
    measured value is newly equal to expected value
    """
    return self._add_listener((self._handle_count, Conditions.equal_to, repetitive, expected, function, args, kwargs))

  def not_equal_to(self, expected, repetitive: bool, function: callable, *args, **kwargs):
    """
    provided function with arguments will be called when
    measured value is newly not equal to expected value
    """
    return self._add_listener((self._handle_count, Conditions.not_equal_to, repetitive, expected, function, args, kwargs))


  def less_than(self, expected, repetitive: bool, function: callable, *args, **kwargs):
    """
    provided function with arguments will be called when
    measured value is newly smaller than expected value
    """
    return self._add_listener((self._handle_count, Conditions.less_than, repetitive, expected, function, args, kwargs))

  def more_than(self, expected, repetitive:bool, function: callable, *args, **kwargs):
    """
    provided function with arguments will be called when
    measured value is newly bigger than expected value
    """
    return self._add_listener((self._handle_count, Conditions.more_than, repetitive, expected, function, args, kwargs))

  def in_range(self, expected_min, expected_max, repetitive: bool, function: callable, *args, **kwargs):
    """
    provided function with arguments will be called when
    measured value is newly bigger or equal to expected_min value and smaller that expected_max value
    """
    return self._add_listener((self._handle_count, Conditions.in_range, repetitive, expected_min, expected_max, function, args, kwargs))

  def out_of_range(self, expected_min, expected_max, repetitive: bool, function: callable, *args, **kwargs):
    """
    provided function with arguments will be called when
    measured value is newly smaller than expected_min value or bigger or equal to expected_max value
    """
    return self._add_listener((self._handle_count, Conditions.out_of_range, repetitive, expected_min, expected_max, function, args, kwargs))

  def changed(self, repetitive: bool, function: callable, *args, **kwargs):
    """
    provided function with arguments will be called when
    measured value is different that last time measured value
    """
    return self._add_listener((self._handle_count, Conditions.value_changed, repetitive, function, args, kwargs))

  def updated(self, repetitive: bool, function: callable, *args, **kwargs):
    """
    provided function with arguments will be called always when
    a value is measured
    """
    return self._add_listener((self._handle_count, Conditions.value_updated, repetitive, function, args, kwargs))

  def __str__(self):
    return str(self.get())
Пример #16
0
class Plan():
    near_barrier = 300
    far_barrier = 600
    open_space = 900

    def __init__(self) -> None:
        self.logging = Logging("events")
        self.chassis = Chassis(power_measurement_period=0.3)
        self.rgb = RgbLedBlock()
        self.display = DisplayBlock()
        self.distance = DistanceBlock(measurement_period=0.1)
        self.button = ButtonBlock(measurement_period=0.1)
        self.ir_block = IrBlock()
        self.ir_block.add_remote(IrNumericRemote())

        self.button.value.equal_to(True, True, self.change_patrol)

        self.near_barrier_event = None
        self.far_bariier_event = None
        self.enough_space_event = None
        self.open_space_event = None
        self.patrol = False

        self.display.contrast(0)
        Ble.value_remote.equal_to(RemoteKey("a"), True, self.turn_left)
        Ble.value_remote.equal_to(RemoteKey("d"), True, self.turn_right)
        Ble.value_remote.equal_to(RemoteKey("w"), True, self.speed_up)
        Ble.value_remote.equal_to(RemoteKey("s"), True, self.slow_down)
        Ble.value_remote.equal_to(RemoteKey("z"), True, self.stop)
        Ble.value_remote.equal_to(RemoteKey("x"), True, self.reverse)
        Ble.value_remote.equal_to(RemoteKey("p"), True, self.change_patrol)

        self.ir_block.value.equal_to(IrNumericRemote.key_left, True,
                                     self.turn_left)
        self.ir_block.value.equal_to(IrNumericRemote.key_right, True,
                                     self.turn_right)
        self.ir_block.value.equal_to(IrNumericRemote.key_top, True,
                                     self.speed_up)
        self.ir_block.value.equal_to(IrNumericRemote.key_bottom, True,
                                     self.slow_down)
        self.ir_block.value.equal_to(IrNumericRemote.key_ok, True, self.stop)
        self.ir_block.value.equal_to(IrNumericRemote.key_hash, True,
                                     self.reverse)
        self.ir_block.value.equal_to(IrNumericRemote.key_star, True,
                                     self.change_patrol)

        self.counter = 0
        Planner.repeat(0.5, self.print_power_info)
        PowerMgmt.set_plan(PowerPlan.get_max_performance_plan())

        self.current_smoother = SmoothedVariable(
            3, SmoothingType.average, self.chassis.power.battery_current_mA)
        self.current_smoother.more_than(600, True, self.stop_for_a_while, 1)
        self.heart_beat = False

    def define_patrol_events(self):
        self.near_barrier_event = self.distance.value.less_than(
            self.near_barrier, True, self.near_barrier_detected)
        self.far_bariier_event = self.distance.value.in_range(
            self.near_barrier, self.far_barrier, True,
            self.far_barrier_detected)
        self.enough_space_event = self.distance.value.in_range(
            self.far_barrier, self.open_space, True,
            self.enough_space_detected)
        self.open_space_event = self.distance.value.more_than(
            self.open_space - 1, True, self.open_space_detected)

    def cancel_patrol_events(self):
        self.distance.value.remove_trigger(self.near_barrier_event)
        self.distance.value.remove_trigger(self.far_bariier_event)
        self.distance.value.remove_trigger(self.enough_space_event)
        self.distance.value.remove_trigger(self.open_space_event)

    def near_barrier_detected(self):
        self.logging.info("near_barrier_detected")
        self.rgb.set_color(RgbLedBlockColor.red)
        self.chassis.set_speed(Speed.slow)
        self.chassis.set_direction(Direction.backward)
        self.chassis.set_manoeuver(
            Manoeuver.sharply_right)  #with reverse will turn left

    def far_barrier_detected(self):
        self.logging.info("far_barrier_detected")
        self.rgb.set_color(RgbLedBlockColor.orange)
        self.chassis.set_speed(Speed.slow)
        self.chassis.set_direction(Direction.forward)
        self.chassis.set_manoeuver(Manoeuver.straight)

    def enough_space_detected(self):
        self.logging.info("enough_space")
        self.rgb.set_color(RgbLedBlockColor.blue)
        self.chassis.set_speed(Speed.normal)
        self.chassis.set_direction(Direction.forward)
        self.chassis.set_manoeuver(Manoeuver.straight)

    def open_space_detected(self):
        self.logging.info("open_space")
        self.rgb.set_color(RgbLedBlockColor.green)
        self.chassis.set_speed(Speed.normal)
        self.chassis.set_direction(Direction.forward)
        self.chassis.set_manoeuver(
            Manoeuver.slightly_right)  #can rotate another wat

    def change_patrol(self):
        if self.patrol:
            self.logging.info("patrol mode canceled")
            self.cancel_patrol_events()
            self.chassis.set_speed(Speed.stop)
        else:
            self.logging.info("patrol mode activated")
            self.define_patrol_events()
            self.chassis.set_speed(Speed.slow)
        self.patrol = not self.patrol

    def print_power_info(self):
        voltage = self.chassis.power.battery_voltage_V.get()

        self.display.clean()
        self.heart_beat = not self.heart_beat
        if self.heart_beat:
            self.display.print_text(55, 0, "*")
        self.display.print_text(0, 9, "%2.3f V" % voltage)

        self.display.print_text(0, 18,
                                "%3.2f mA" % self.current_smoother.get())
        self.display.print_text(0, 36, str(self.distance.value.get()))
        self.counter += 1
        self.display.showtime()

    def slow_down(self):
        self.chassis.set_speed(self.chassis.speed - 1)

    def speed_up(self):
        self.chassis.set_speed(self.chassis.speed + 1)

    def turn_left(self):
        self.chassis.set_manoeuver(self.chassis.manoeuver - 1)

    def turn_right(self):
        self.chassis.set_manoeuver(self.chassis.manoeuver + 1)

    def reverse(self):
        self.logging.info(self.chassis.direction == Direction.forward)
        self.chassis.set_direction(Direction.backward if self.chassis.direction
                                   == Direction.forward else Direction.forward)

    def stop_for_a_while(self, delay):
        self.stop()  #take a rest
        Planner.postpone(delay, self.chassis.set_speed,
                         Speed.slow)  #... and slowly continue

    def stop(self):
        self.chassis.set_speed(Speed.stop)
        self.chassis.set_manoeuver(Manoeuver.straight)
Пример #17
0
class Plan():
    fullspeed = 100
    logging = Logging("events")

    def __init__(self) -> None:
        self.speed = 0
        self.pwm = 50

        Ble.value_remote.equal_to(RemoteKey("a"), True, self.pwm_down)
        Ble.value_remote.equal_to(RemoteKey("d"), True, self.pwm_up)
        Ble.value_remote.equal_to(RemoteKey("w"), True, self.speed_up)
        Ble.value_remote.equal_to(RemoteKey("s"), True, self.slow_down)
        Ble.value_remote.equal_to(RemoteKey("z"), True, self.stop)
        Ble.value_remote.equal_to(RemoteKey("o"), True, self.full_speed_up)
        Ble.value_remote.equal_to(RemoteKey("l"), True, self.full_speed_down)

        self.motor_driver_front = MotorDriverBlock(0x20)
        #self.motor_driver_front.change_block_address(0x20)
        self.motor_driver_front.turn_clockwise(MotorDriverBlock.motor1_id)
        self.motor_driver_front.turn_opposite(MotorDriverBlock.motor2_id)

        self.motor_driver_rear = MotorDriverBlock(0x21)
        #self.motor_driver_rear.change_block_address(0x21)
        self.motor_driver_rear.turn_clockwise(MotorDriverBlock.motor1_id)
        self.motor_driver_rear.turn_opposite(MotorDriverBlock.motor2_id)

        self.motor_driver_front.sensor_power_on()
        self.motor_driver_rear.sensor_power_on()
        self.motor_driver_front.reset_sensor_counter(
            MotorDriverBlock.motor1_id)
        self.motor_driver_front.reset_sensor_counter(
            MotorDriverBlock.motor2_id)
        self.motor_driver_rear.reset_sensor_counter(MotorDriverBlock.motor1_id)
        self.motor_driver_rear.reset_sensor_counter(MotorDriverBlock.motor2_id)

        Planner.repeat(1, self.print_counters)

    def print_counters(self):
        counter11 = self.motor_driver_front.get_sensor_counter(
            MotorDriverBlock.motor1_id)
        counter12 = self.motor_driver_front.get_sensor_counter(
            MotorDriverBlock.motor2_id)
        counter21 = self.motor_driver_rear.get_sensor_counter(
            MotorDriverBlock.motor1_id)
        counter22 = self.motor_driver_rear.get_sensor_counter(
            MotorDriverBlock.motor2_id)
        self.logging.info(
            "counter11: {0}, counter12: {1}, counter21: {2}, counter22: {3}".
            format(counter11, counter12, counter21, counter22))

    def _adjust_motors(self):
        self.logging.info("fullspeed: %d, speed: %d, pwm: %d" %
                          (self.fullspeed, self.speed, self.pwm))
        fullspeed = 0
        if self.fullspeed > 0:
            self.motor_driver_front.turn_clockwise(MotorDriverBlock.motor1_id)
            self.motor_driver_rear.turn_clockwise(MotorDriverBlock.motor1_id)
            fullspeed = self.fullspeed
        else:
            self.motor_driver_front.turn_opposite(MotorDriverBlock.motor1_id)
            self.motor_driver_rear.turn_opposite(MotorDriverBlock.motor1_id)
            fullspeed = self.fullspeed * -1

        self.motor_driver_front.set_speed(MotorDriverBlock.motor1_id,
                                          fullspeed)
        self.motor_driver_front.set_speed(MotorDriverBlock.motor2_id,
                                          self.speed)

        self.motor_driver_rear.set_speed(MotorDriverBlock.motor1_id, fullspeed)
        self.motor_driver_rear.set_speed(MotorDriverBlock.motor2_id,
                                         self.speed)
        self.motor_driver_front.set_pwm_period(self.pwm)
        self.motor_driver_rear.set_pwm_period(self.pwm)

    def full_speed_up(self):
        self.fullspeed += 10
        self._adjust_motors()

    def full_speed_down(self):
        self.fullspeed -= 10
        self._adjust_motors()

    def pwm_up(self):
        self.pwm += 10
        self._adjust_motors()

    def pwm_down(self):
        self.pwm -= 10
        self._adjust_motors()

    def speed_up(self):
        self.speed += 5
        self._adjust_motors()

    def slow_down(self):
        self.speed -= 5
        self._adjust_motors()

    def stop(self):
        self.motor_driver_front.stop(MotorDriverBlock.motor1_id)
        self.motor_driver_front.stop(MotorDriverBlock.motor2_id)
        self.motor_driver_rear.stop(MotorDriverBlock.motor1_id)
        self.motor_driver_rear.stop(MotorDriverBlock.motor2_id)
Пример #18
0
class Map:
    def __init__(self, dim_x, dim_y) -> None:
        self.logging = Logging("map")
        self.map_layers = []
        self.current_x = 0
        self.dim_x = dim_x
        self.dim_y = dim_y
        self.removed_count = 0
        self.init()

    def add_map_layer(self, top_y, bottom_y, diamond):
        self.map_layers.append(MapLayer(top_y, bottom_y, diamond))

    def get_borders(self, x):
        pos = self.current_x + x - self.removed_count
        try:
            layer = self.map_layers[pos]
            return layer.top, self.dim_y - layer.bottom
        except Exception:
            self.logging.error(pos)

    def remove_diamond(self, diamond):
        for layer in self.map_layers:
            if layer.diamond == diamond:
                layer.diamond = None

    def get_diamonds(self, x):
        diamonds = list()
        for current_x in range(x - int(Diamond.max_dim),
                               x + int(Diamond.max_dim) + 1):

            pos = self.current_x + current_x - self.removed_count
            layer = self.map_layers[pos]
            if layer.diamond:
                diamonds.append(layer.diamond)
        return diamonds

    def add_random_layers(self, count):
        for _index in range(count):
            top_min = 8
            bottom_min = 0
            last_top = self.map_layers[-1].top
            last_bottom = self.map_layers[-1].bottom
            change_top = int(random.random() * 3) - 1
            change_bottom = int(random.random() * 3) - 1
            top_pos = last_top - change_top if last_top - change_top > top_min else top_min
            bottom_pos = last_bottom - change_bottom if last_bottom - change_bottom > bottom_min else bottom_min
            if top_pos + bottom_pos > self.dim_y - 20:
                if top_pos - top_min > bottom_pos:
                    top_pos -= top_pos + bottom_pos - (self.dim_y - 20)
                else:
                    bottom_pos -= top_pos + bottom_pos - (self.dim_y - 20)

            diamond = None
            if self.current_x + _index > 10 and (self.current_x + _index) % (
                    Diamond.max_dim * 2) == 0 and int(
                        random.random() * 10) > 5:
                is_top = True if int(random.random() * 2) else False
                dimension = int(random.random() *
                                (Diamond.dim_diff * 2 +
                                 1)) - Diamond.dim_diff + Diamond.base_dim

                embedding = 1 if dimension < Diamond.base_dim else 2
                if is_top:
                    diamond = Diamond(top_pos + dimension - embedding, True,
                                      dimension)
                else:
                    diamond = Diamond(
                        self.dim_y - bottom_pos - dimension + embedding, False,
                        dimension)
            self.add_map_layer(top_pos, bottom_pos, diamond)

    def remove_first_layers(self, count):
        self.map_layers = self.map_layers[count:]
        self.removed_count += count

    def init(self):
        self.map_layers = []
        self.add_map_layer(11, 2, None)
        self.add_random_layers(100)
        self.current_x = 0

    def is_enough_data(self):
        return self.current_x - self.removed_count + self.dim_x < len(
            self.map_layers)

    def draw(self, display: DisplayBlock):
        for x in range(self.dim_x):
            pos = self.current_x + x - self.removed_count
            if x >= 0:
                layer = self.map_layers[pos]
                display.draw_line(x, layer.top, x, 0)
                display.draw_line(x, self.dim_y - layer.bottom - 1, x,
                                  self.dim_y - 1)
                if layer.diamond:
                    layer.diamond.draw(x, display)
Пример #19
0
class Plan:
    def __init__(self):
        self.started = False
        self.display = DisplayBlock()
        self.logging = Logging("plan")
        self.button = ButtonBlock()
        self.rgb = RgbLedBlock()
        self.led_default()
        self.dim_x, self.dim_y = self.display.get_dimensions()
        self.center_x = int(self.dim_x / 2)
        self.center_y = int(self.dim_y / 2)
        self.point = None
        self.map = None
        self.score = 0

        self.wait_for_start()
        self.redraw()

    def wait_for_start(self):
        self.started = False
        self.score = 0
        self.point = Point(self.center_y)
        self.map = Map(self.dim_x, self.dim_y)
        self.display.invert(True)
        self.button.value.changed(False, self.start_button)
        gc.collect()  #force garbage collection before game starts

    def start_button(self):
        self.started = True
        self.logging.info("started")
        self.redraw()
        self.led_default()

    def redraw(self):
        speed = int(self.map.current_x / 400) + 1
        if speed > 10:
            speed = 10

        if not self.map.is_enough_data():
            remove_step_count = speed
            self.map.remove_first_layers(remove_step_count)
            self.map.add_random_layers(remove_step_count)

        self.display.clean()
        self.point.draw(self.display)
        if self.started:
            if self.button.value.get():
                self.point.y -= 2
            else:
                self.point.y += 2

        border_top, border_bottom = self.map.get_borders(self.point.x)

        touch = False
        if self.point.y < border_top + self.point.r - 1:
            self.point.y = border_top + self.point.r
            touch = True

        if self.point.y > border_bottom - self.point.r:
            self.point.y = border_bottom - self.point.r
            touch = True

        if not touch:
            diamonds = self.map.get_diamonds(self.point.x)
            for diamond in diamonds:
                if diamond.is_in_area(self.point.y - self.point.r,
                                      self.point.y + self.point.r):
                    self.map.remove_diamond(diamond)
                    self.score += 1
                    self.rgb.set_color(RgbLedBlockColor.green)
                    Planner.postpone(0.05, self.led_default)

        self.map.draw(self.display)
        if self.started:
            self.display.invert(False if touch else True)
            self.map.current_x += speed
        #score = int(self.map.current_x / 10)
        self.display.print_text(0, 0, str(self.score), color=0)
        self.display.showtime()
        if not touch:
            Planner.postpone(0.05, self.redraw)
        else:
            self.started = False
            self.rgb.set_color(RgbLedBlockColor.red)
            Planner.postpone(
                1, self.wait_for_reset_pressed
            )  #wait a while to prevent random press and wait for starting new game

    def led_default(self):
        self.rgb.set_color(RgbLedBlockColor.aquamarine)

    def wait_for_reset_pressed(self):
        self.button.value.equal_to(True, False, self.wait_for_reset_released)

    def wait_for_reset_released(self):
        self.button.value.equal_to(False, False, self.wait_for_start)
Пример #20
0
 def __init__(self) -> None:
     self.button = ButtonBlock(measurement_period=0.1)
     self.led = RgbLedBlock()
     self.logging = Logging()
     self.button.value.changed(True, self._button_state_changed)
Пример #21
0
class Shell():
  events_file_name = "events.mpy"
  do_not_import_file_name = ".do_not_import_import"

  file_path = None
  new_file = False
  path = [""]
  dir_contents = list()
  dir_positions = list()
  logging = Logging("Shell")
  events_imported = False

  @classmethod
  def file_exists(cls, path):
    try:
      file = open(path, "r")
      file.close()
      return True
    except OSError:  # open failed
      return False

  @classmethod
  def create_file(cls, file_path):
    with open(file_path, "w"):
      pass

  @classmethod
  def remove_file(cls, file_path):
    os.remove(file_path)

  @classmethod
  def rename_file(cls, orig_file_path, dest_file_path):
    os.rename(orig_file_path, dest_file_path)

  @classmethod
  def _reboot(cls):
    MainBlock.reboot()

  @classmethod
  def _import_events(cls):
    if not cls.file_exists(cls.events_file_name):
      print("events file not found")
      return False
    try:
      print("events will be imported")
      import events #events will planned
      cls.logging.info("events loaded successfully")
      cls.events_imported = True
      return True
    except Exception as error:
      cls.logging.exception(error, extra_message="events.py was not imported properly")
      import sys
      sys.print_exception(error, sys.stdout)
      return False

  @classmethod
  def load_events(cls):
    if cls.file_exists(cls.do_not_import_file_name):
      print("do_not_import_file_name removed")
      cls.remove_file(cls.do_not_import_file_name)
    else:
      cls._import_events()

  @classmethod
  def read_chunks(file, chunk_size):
    while True:
      data = file.read(chunk_size)
      if not data:
        break
      yield data

  @classmethod
  def _get_file_checksum(cls, file_path):
    sha1 = hashlib.sha1(b"")
    with open(file_path, "rb") as file:
      while True:
        chunk = file.read(1000)
        if not chunk:
          break
        sha1.update(chunk)
    return sha1.digest()

  @classmethod
  def _get_path(cls):
    path = ""
    for item in cls.path:
      path += item + "/"
    return path

  @classmethod
  def _is_file(cls, path):
    try:
      f = open(path, "r")
      f.close()
      return True
    except OSError:
      return False

  @classmethod
  def _get_next_file_info(cls):
    path = cls._get_path()
    if len(cls.dir_contents) < len(cls.path):
      cls.dir_contents.append(os.listdir(path))
      cls.dir_positions.append(0)

    if cls.dir_positions[-1] >= len(cls.dir_contents[-1]):
      if len(cls.dir_positions) > 1:
        cls.dir_contents = cls.dir_contents[:-1]
        cls.dir_positions = cls.dir_positions[:-1]
        cls.path = cls.path[:-1]
        return cls._get_next_file_info()
      else:
        return ble_ids.b_false #proceses last file of root directory

    name = cls.dir_contents[-1][cls.dir_positions[-1]]
    file_path = path + name

    cls.dir_positions[-1] += 1
    if cls._is_file(file_path):
      return cls._get_file_checksum(file_path) + file_path.encode("utf-8")
    else:
      cls.path.append(name)
      return cls._get_next_file_info()

  @classmethod
  def command_request(cls, command, data):
    if command == ble_ids.cmd_common_version:
      return ble_ids.b_true
    elif command == ble_ids.cmd_shell_program_started:
      return (ble_ids.b_true if cls.events_imported else ble_ids.b_false)
    elif command == ble_ids.cmd_shell_stop_program:
      print("cmd_stop_program")
      if data[0] == ble_ids.b_true and cls.file_exists(cls.events_file_name):
        print("do not import file will be created")
        cls.create_file(cls.do_not_import_file_name)

      print("reboot planned")
      Planner.postpone(0.1, cls._reboot)
      return ble_ids.b_true

    elif command == ble_ids.cmd_shell_start_program:
      return (ble_ids.b_true if cls._import_events() else ble_ids.b_false)

    elif command == ble_ids.cmd_shell_get_next_file_info:
      return cls._get_next_file_info()

    elif command == ble_ids.cmd_shell_remove_file:
      cls.remove_file(data)
      return ble_ids.b_true

    elif command == ble_ids.cmd_shell_handle_file:
      cls.handeled_file_path = data
      cls.new_file = True
      return ble_ids.b_true

    elif command == ble_ids.cmd_shell_get_file_checksum:
      return cls._get_file_checksum(cls.handeled_file_path)

    elif command == ble_ids.cmd_shell_append:
      if cls.new_file:
        file = open(cls.handeled_file_path, "wb")
        cls.new_file = False
      else:
        file = open(cls.handeled_file_path, "ab")

      file.write(data)
      file.close()
      return ble_ids.b_true

    elif command == ble_ids.cmd_shell_mk_dir:
      try:
        os.mkdir(data)
      except Exception:
        return ble_ids.b_false
      return ble_ids.b_true

    else:
      return None
Пример #22
0
 def _info(cls, message_id:str, activeVariable:ActiveVariable):
   Logging(message_id).value(str(activeVariable))
Пример #23
0
#  Copyright (c) 2022 Jakub Vesely
#  This software is published under MIT license. Full text of the license is available at https://opensource.org/licenses/MIT

from basal.logging import Logging
from basal.power_mgmt import PowerMgmt
import sys
import time
import uasyncio
import gc

logging = Logging("planner")
unhandled_exception_prefix = "Unhandled exception"


class TaskProperties:
    kill = False
    waiting_start_ms = 0
    waiting_time_ms = 0


class Planner:
    _performed_tasks = {
    }  #expected dict with task handle as key and tasks properties as value
    _handle_count = 0
    _loop = uasyncio.get_event_loop()
    _power_mgmt = PowerMgmt()

    @classmethod
    def _get_next_handle(cls):
        handle = cls._handle_count
        cls._handle_count += 1
Пример #24
0
class BlockBase:
    i2c = machine.I2C(0, scl=machine.Pin(22), sda=machine.Pin(21), freq=100000)

    def __init__(self, block_type: BlockType, address: int):
        self.type_id = block_type.id
        self.address = address if address else block_type.id  #default block i2c address is equal to its block type

        self.block_type_valid = False
        self.logging = Logging(block_type.name.decode("utf-8"))
        self.block_version = self._get_block_version()

        self.power_save_level = PowerSaveLevel.NoPowerSave
        self._tiny_write_base_id(_power_save_command,
                                 self.power_save_level.to_bytes(1, 'big'),
                                 True)  #wake up block functionality

        if not self.block_version:
            self.logging.warning("module with address 0x%x is not available",
                                 self.address)
        elif self.block_version[0] != self.type_id:
            self.logging.error(
                "unexpected block type. expected: %d, returned: %d",
                self.type_id, self.block_version[0])
        else:
            self.block_type_valid = True

    def _raw_tiny_write(self,
                        type_id: int,
                        command: int,
                        data=None,
                        silent=False):
        try:
            payload = type_id.to_bytes(1, 'big') + command.to_bytes(1, 'big')

            if data:
                payload += data
            #self.logging.info(("write", payload))
            self.i2c.writeto(self.address, payload)
        except OSError:
            if not silent:
                self.logging.error(
                    "tiny-block with address 0x%02X is unavailable for writing",
                    self.address)

    def _check_type(self, type_id):
        return type_id in (_i2c_block_type_id_base,
                           self.type_id) and (_i2c_block_type_id_base
                                              or self.block_type_valid)

    def __tiny_write_common(self,
                            type_id: int,
                            command: int,
                            data=None,
                            silent=False):
        """
    writes data to tiny_block via I2C
    @param type_id: block type id
    @param command: one byte command
    @param data: specify input data for entered command
    """
        if self._check_type(type_id):
            self._raw_tiny_write(type_id, command, data, silent)
        else:
            self.logging.error("invalid block type - writing interupted")

    def _tiny_write_base_id(self, command: int, data=None, silent=False):
        self.__tiny_write_common(_i2c_block_type_id_base, command, data,
                                 silent)

    def _tiny_write(self, command: int, data=None, silent=False):
        if not self.is_available():
            return
        self.__tiny_write_common(self.type_id, command, data, silent)

    def __tiny_read_common(self,
                           type_id: int,
                           command: int,
                           in_data: typing.Union[bytes, None] = None,
                           expected_length: int = 0,
                           silent=False):
        """
    reads data form tiny_block via I2C
    @param type_id: block type id
    @param command: one byte command
    @param in_data: specify input data for entered command
    @param expected_length: if defined will be read entered number of bytes. If None is expected length as a first byte
    @return provided bytes. If size is first byte is not included to output data
    """
        if self._check_type(type_id):
            self._raw_tiny_write(type_id, command, in_data, silent)
            try:
                data = self.i2c.readfrom(self.address, expected_length, True)
                return data
            except OSError:
                if not silent:
                    self.logging.error(
                        "tiny-block with address 0x%02X is unavailable for reading",
                        self.address)
            return None
        else:
            self.logging.error("invalid block type - reading interupted")
            return None

    def _tiny_read_base_id(self,
                           command: int,
                           in_data: typing.Union[bytes, None] = None,
                           expected_length: int = 0,
                           silent=False):
        return self.__tiny_read_common(_i2c_block_type_id_base, command,
                                       in_data, expected_length, silent)

    def _tiny_read(self,
                   command: int,
                   in_data: typing.Union[bytes, None] = None,
                   expected_length: int = 0):
        if not self.is_available():
            return None

        return self.__tiny_read_common(self.type_id, command, in_data,
                                       expected_length)

    def change_block_address(self, new_address):
        self._tiny_write_base_id(_change_i2c_address_command,
                                 new_address.to_bytes(1, 'big'))
        self.address = new_address
        time.sleep(0.1)  #wait to the change is performed and stopped

    def _get_block_version(self):
        """
    returns block_type, pcb version, adjustment_version
    """
        data = self._tiny_read_base_id(_get_module_version_command,
                                       None,
                                       3,
                                       silent=True)
        if not data:
            return b""
        return (data[0], data[1], data[2])

    def is_available(self):
        return self.block_type_valid  #available and valid block version

    def power_save(self, level: int) -> None:
        """
    level is aPowerSaveLevel value
    """
        self.power_save_level = level
        self._tiny_write_base_id(_power_save_command, level.to_bytes(1, 'big'))