Example #1
0
 async def send_messages(self):
     """
     Send messages in the queue to the sensor.
     """
     await self._ready.wait()
     while not self.transport.is_closing():
         instruction, args = await self.write_queue.get()
         if instruction == "ping":
             hm.send(self.transport, hm.make_ping())
         elif instruction == "subscribe":
             uid, delay, params = args
             hm.send(
                 self.transport,
                 hm.make_subscription_request(hm.uid_to_device_id(uid),
                                              params, delay))
         elif instruction == "read":
             uid, params = args
             hm.send(self.transport,
                     hm.make_device_read(hm.uid_to_device_id(uid), params))
         elif instruction == "write":
             uid, params_and_values = args
             hm.send(
                 self.transport,
                 hm.make_device_write(hm.uid_to_device_id(uid),
                                      params_and_values))
         elif instruction == "disable":
             hm.send(self.transport, hm.make_disable())
         elif instruction == "heartResp":
             uid = args[0]
             hm.send(self.transport,
                     hm.make_heartbeat_response(self.read_queue.qsize()))
Example #2
0
def device_write_thread(ser, instr_queue):
    """
    Send packets to SER based on instructions from INSTR_QUEUE.
    """
    try:
        while True:
            instruction, args = instr_queue.get()

            if instruction == "ping":
                hm.send(ser, hm.make_ping())
            elif instruction == "subscribe":
                uid, delay, params = args
                hm.send(
                    ser,
                    hm.make_subscription_request(hm.uid_to_device_id(uid),
                                                 params, delay))
            elif instruction == "read":
                uid, params = args
                hm.send(ser,
                        hm.make_device_read(hm.uid_to_device_id(uid), params))
            elif instruction == "write":
                uid, params_and_values = args
                hm.send(
                    ser,
                    hm.make_device_write(hm.uid_to_device_id(uid),
                                         params_and_values))
            elif instruction == "disable":
                hm.send(ser, hm.make_disable())
            elif instruction == "heartResp":
                uid = args[0]
                hm.send(ser, hm.make_heartbeat_response())
    except serial.SerialException:
        # Device has disconnected
        pass
Example #3
0
 async def recv_messages(self):
     """
     Process received messages.
     """
     await self._ready.wait()
     while not self.transport.is_closing():
         if self.read_queue.qsize() >= PAUSE_QUEUE_SIZE:
             self.transport.pause_reading()
         if self.read_queue.qsize() <= RESUME_QUEUE_SIZE:
             self.transport.resume_reading()
         packet = await self.read_queue.get()
         message_type = packet.get_message_id()
         if message_type == hm.MESSAGE_TYPES["SubscriptionResponse"]:
             params, delay, uid = hm.parse_subscription_response(packet)
             self.uid = uid
             await self.state_queue.coro_put(
                 ("device_subscribed", [uid, delay, params]))
         elif message_type == hm.MESSAGE_TYPES["DeviceData"]:
             # This is kind of a hack, but it allows us to use `recv_messages` for
             # detecting new smart sensors as well as reading from known ones.
             if self.uid is not None:
                 params_and_values = hm.parse_device_data(
                     packet, hm.uid_to_device_id(self.uid))
                 self.batched_data[uid] = params_and_values
         elif message_type == hm.MESSAGE_TYPES["HeartBeatRequest"]:
             if self.uid is not None:
                 self.write_queue.put_nowait(("heartResp", [self.uid]))
Example #4
0
def device_read_thread(uid, pack, error_queue, state_queue, batched_data):
    """
    Read packets from SER and update queues and BATCHED_DATA accordingly.
    """
    ser = pack.serial_port
    instruction_queue = pack.write_queue
    try:
        while True:
            for packet in hm.blocking_read_generator(ser):
                message_type = packet.get_message_id()
                if message_type == hm.MESSAGE_TYPES["SubscriptionResponse"]:
                    params, delay, uid = hm.parse_subscription_response(packet)
                    state_queue.put(("device_subscribed", [uid, delay,
                                                           params]))
                elif message_type == hm.MESSAGE_TYPES["DeviceData"]:
                    params_and_values = hm.parse_device_data(
                        packet, hm.uid_to_device_id(uid))
                    batched_data[uid] = params_and_values
                elif message_type == hm.MESSAGE_TYPES["HeartBeatRequest"]:
                    instruction_queue.put(("heartResp", [uid]))
    except serial.SerialException:
        error = namedtuple("Disconnect", ["uid", "instance_id", "accessed"])
        error.uid = uid
        error.instance_id = pack.instance_id
        error.accessed = False
        error_queue.put(error)
Example #5
0
def main_interface():
    """
    Render the main interface page.
    """
    HIBIKE_INSTANCE.subscribe_all()
    from collections import namedtuple
    import time
    # Wait for Hibike to read from devices
    time.sleep(0.5)
    devices = []
    for uid in HIBIKE_INSTANCE.uids:
        dev_id = hibike_message.uid_to_device_id(uid)
        dev_name = hibike_message.uid_to_device_name(uid)
        all_params = hibike_message.all_params_for_device_id(dev_id)
        params_list = []
        for param_name in all_params:
            param = namedtuple(
                "Parameter",
                ("name", "type", "readable", "writeable", "init_value"))
            param.name = param_name
            param.type = hibike_message.param_type(dev_id, param_name)
            param.writeable = hibike_message.writable(dev_id, param_name)
            param.readable = hibike_message.readable(dev_id, param_name)
            param.init_value = HIBIKE_INSTANCE.get_last_cached(uid, param_name)
            params_list.append(param)
        params_list.sort(key=lambda p: p.name)
        device = namedtuple("Device", ("uid", "params", "name"))
        device.uid = uid
        device.params = params_list
        device.name = dev_name
        devices.append(device)
    return render_template("index.html", devices=devices)
Example #6
0
 def __init__(self, serial_port, params, delay, uid):
     self.serial_port = serial_port
     self.uid = uid
     self.device_type = hm.uid_to_device_id(uid)
     self.params = params
     self.delay = delay
     self.data = defaultdict(lambda: (None, -1))
 def gen_random_sub_response():
     """ Generate a random subscription response packet. """
     uid = random_uid()
     device_id = hibike_message.uid_to_device_id(uid)
     params = random_params(device_id)
     delay = random.randrange(100)
     msg = hibike_message.make_subscription_response(
         device_id, params, delay, uid)
     return (ParsingTests.encode_packet(msg), )
Example #8
0
def read_param(uid, param):
    """
    Read a single device parameter.
    """
    if uid not in HIBIKE_INSTANCE.uids:
        abort(404)
    params = hibike_message.all_params_for_device_id(hibike_message.uid_to_device_id(uid))
    if param not in params:
        abort(404)
    return json.dumps({param: HIBIKE_INSTANCE.get_last_cached(uid, param)})
Example #9
0
def device_write_thread(ser, queue):
    while True:
        instruction, args = queue.get()

        if instruction == "ping":
            hm.send(ser, hm.make_ping())
        elif instruction == "subscribe":
            uid, delay, params = args
            hm.send(
                ser,
                hm.make_subscription_request(hm.uid_to_device_id(uid), params,
                                             delay))
        elif instruction == "read":
            uid, params = args
            hm.send(ser, hm.make_device_read(hm.uid_to_device_id(uid), params))
        elif instruction == "write":
            uid, params_and_values = args
            hm.send(
                ser,
                hm.make_device_write(hm.uid_to_device_id(uid),
                                     params_and_values))
Example #10
0
 def subscribe_all(self):
     """
     Subscribe to all devices with all parameters.
     """
     for uid in self.uids:
         dev_id = hibike_message.uid_to_device_id(uid)
         all_params = hibike_message.all_params_for_device_id(dev_id)
         readable_params = []
         for param in all_params:
             if hibike_message.readable(dev_id, param):
                 readable_params.append(param)
         self.pipe_to_child.send(["subscribe_device", [uid, self.DEFAULT_DELAY,
                                                       readable_params]])
Example #11
0
 def _process_sub_request(self, msg):
     """Respond to a subscription request with an appropriate response."""
     self.update_time = time.time()
     dev_id = hm.uid_to_device_id(self.uid)
     self.verbose_log("Subscription request received")
     params, delay = struct.unpack("<HH", msg.get_payload())
     subscribed_params = hm.decode_params(dev_id, params)
     hm.send(
         self.transport,
         hm.make_subscription_response(dev_id, subscribed_params, delay,
                                       self.uid))
     self.delay = delay
     self.subscribed_params.update(set(subscribed_params))
Example #12
0
def read_all_params(uid):
    """
    Read all parameters from a device.
    """
    if uid not in HIBIKE_INSTANCE.uids:
        abort(404)
    dev_id = hibike_message.uid_to_device_id(uid)
    all_params = hibike_message.all_params_for_device_id(dev_id)
    readable_params = [p for p in all_params if hibike_message.readable(dev_id, p)]
    param_values = {}
    for param in readable_params:
        param_values[param] = HIBIKE_INSTANCE.get_last_cached(uid, param)
    return json.dumps(param_values)
Example #13
0
    def _process_device_read(self, msg):
        self.verbose_log("Device read received")
        device_id = hm.uid_to_device_id(self.uid)
        # Send a device data with the requested param and value tuples
        params, = struct.unpack("<H", msg.get_payload())
        read_params = hm.decode_params(device_id, params)
        read_data = []

        for param in read_params:
            if not (hm.readable(device_id, param)
                    and param in self.param_values):
                raise ValueError(
                    "Tried to read unreadable parameter {}".format(param))
            read_data.append((param, self.param_values[param]))
        hm.send(self.transport, hm.make_device_data(device_id, read_data))
Example #14
0
def device_read_thread(index, ser, instructionQueue, errorQueue, stateQueue):
    uid = None
    while True:
        packet = hm.blocking_read(ser)
        message_type = packet.getmessageID()
        if message_type == hm.messageTypes["SubscriptionResponse"]:
            params, delay, uid = hm.parse_subscription_response(packet)
            uid_to_index[uid] = index
            stateQueue.put(("device_subscribed", [uid, delay, params]))
        elif message_type == hm.messageTypes["DeviceData"]:
            if uid is not None:
                params_and_values = hm.parse_device_data(
                    packet, hm.uid_to_device_id(uid))
                stateQueue.put(("device_values", params_and_values))
            else:
                print("[HIBIKE] Port %s received data before enumerating!!!" %
                      ser.port)
Example #15
0
def write_params(uid):
    """
    Write values to a device.
    """
    if uid not in HIBIKE_INSTANCE.uids:
        abort(404)
    all_params = set(hibike_message.all_params_for_device_id(hibike_message.uid_to_device_id(uid)))
    params = request.get_json(force=True, cache=False)
    if params is None:
        abort(400)
    params_and_values = []
    for (param, value) in params.items():
        if param not in all_params:
            abort(400)
        params_and_values.append((param, value))
    HIBIKE_INSTANCE.write(uid, params_and_values)
    return "wrote value"
Example #16
0
 async def register_sensor(self, event_loop, devices, pending):
     """
     Try to get our UID from the sensor and register it with `hibike_process`.
     """
     await self._ready.wait()
     hm.send(self.transport, hm.make_ping())
     await asyncio.sleep(IDENTIFY_TIMEOUT, loop=event_loop)
     if self.uid is None:
         self.quit()
     else:
         hm.send(self.transport, hm.make_ping())
         hm.send(
             self.transport,
             hm.make_subscription_request(hm.uid_to_device_id(self.uid), [],
                                          0))
         devices[self.uid] = self
     pending.remove(self.transport.serial.name)
Example #17
0
def get_device_info(uid):
    """
    Get a dictionary representing information about a device.
    """
    if uid not in HIBIKE_INSTANCE.uids:
        raise DeviceNotFoundError()
    device_id = hibike_message.uid_to_device_id(uid)
    device_name = hibike_message.device_id_to_name(device_id)
    params = hibike_message.all_params_for_device_id(device_id)
    json_map = {"device_name": device_name, "params": []}
    for param in params:
        readable = hibike_message.readable(device_id, param)
        writeable = hibike_message.writable(device_id, param)
        param_type = hibike_message.param_type(device_id, param)
        json_map["params"].append({"name": param,
                                   "readable": readable,
                                   "writeable": writeable,
                                   "type": param_type})
    return json_map
Example #18
0
 async def send_subscribed_params(self):
     """Send values of subscribed parameters at a regular interval."""
     await self._ready.wait()
     device_id = hm.uid_to_device_id(self.uid)
     while not self.transport.is_closing():
         await asyncio.sleep(0.005, loop=self.event_loop)
         if self.update_time != 0 and self.delay != 0:
             if time.time() - self.update_time >= self.delay * 0.001:
                 # If the time equal to the delay has elapsed since the previous device data,
                 # send a device data with the device id
                 # and the device's subscribed params and values
                 data = []
                 for param in self.subscribed_params:
                     data.append((param, self.param_values[param]))
                 hm.send(self.transport,
                         hm.make_device_data(device_id, data))
                 self.update_time = time.time()
                 self.verbose_log("Regular data update sent from {}",
                                  hm.uid_to_device_name(self.uid))
Example #19
0
    def _process_device_write(self, msg):
        # Write to requested parameters
        # and return the values of the parameters written to using a device data
        self.verbose_log("Device write received")
        device_id = hm.uid_to_device_id(self.uid)
        write_params_and_values = hm.decode_device_write(msg, device_id)

        for (param, value) in write_params_and_values:
            if not (hm.writable(device_id, param)
                    and param in self.param_values):
                raise ValueError(
                    "Tried to write read-only parameter: {}".format(param))
            self.param_values[param] = value

        updated_params = []
        for (param, value) in write_params_and_values:
            if hm.readable(device_id, param):
                updated_params.append((param, value))
        hm.send(self.transport, hm.make_device_data(device_id, updated_params))
Example #20
0
 newProcess = multiprocessing.Process(
     target=hibike_process,
     name="hibike_sim",
     args=[badThingsQueue, stateQueue, pipeFromChild])
 newProcess.daemon = True
 newProcess.start()
 pipeToChild.send(["enumerate_all", []])
 uids = set()
 while True:
     print("waiting for command")
     command, args = stateQueue.get()
     if command == "device_subscribed":
         uid = args[0]
         if uid not in uids:
             uids.add(uid)
             if hm.devices[hm.uid_to_device_id(uid)]["name"] == "TeamFlag":
                 set_interval_sequence([
                     make_send_write(pipeToChild, uid, [("led1", 1),
                                                        ("led2", 0),
                                                        ("led3", 0),
                                                        ("led4", 0),
                                                        ("blue", 0),
                                                        ("yellow", 0)]),
                     make_send_write(pipeToChild, uid, [("led1", 0),
                                                        ("led2", 1),
                                                        ("led3", 0),
                                                        ("led4", 0),
                                                        ("blue", 0),
                                                        ("yellow", 0)]),
                     make_send_write(pipeToChild, uid, [("led1", 0),
                                                        ("led2", 0),
 def gen_random_device_id_and_params():
     """ Generate a random device ID and set of parameters. """
     device_id = hibike_message.uid_to_device_id(random_uid())
     params = random_params(device_id)
     return (device_id, params)
Example #22
0
 def _process_ping(self, msg):
     """Respond to a ping packet."""
     self.verbose_log("Ping received")
     dev_id = hm.uid_to_device_id(self.uid)
     hm.send(self.transport,
             hm.make_subscription_response(dev_id, [], 0, self.uid))
Example #23
0
 newProcess = multiprocessing.Process(
     target=hibike_process,
     name="hibike_sim",
     args=[main_error_queue, main_state_queue, from_child])
 newProcess.daemon = True
 newProcess.start()
 to_child.send(["enumerate_all", []])
 uids = set()
 while True:
     print("waiting for command")
     command, main_args = main_state_queue.get()
     if command == "device_subscribed":
         dev_uid = main_args[0]
         if dev_uid not in uids:
             uids.add(dev_uid)
             if hm.DEVICES[hm.uid_to_device_id(
                     dev_uid)]["name"] == "YogiBear":
                 set_interval_sequence([
                     make_send_write(to_child, dev_uid,
                                     [("duty_cycle", 0)]),
                     make_send_write(to_child, dev_uid,
                                     [("duty_cycle", 0.5)]),
                     make_send_write(to_child, dev_uid,
                                     [("duty_cycle", 1.0)]),
                     make_send_write(to_child, dev_uid,
                                     [("duty_cycle", 0)]),
                     make_send_write(to_child, dev_uid,
                                     [("duty_cycle", -0.5)]),
                     make_send_write(to_child, dev_uid,
                                     [("duty_cycle", -1.0)]),
                     make_send_write(to_child, dev_uid, [("duty_cycle", 0)])
                 ], 0.75)