Пример #1
0
class HausNet:
    """Give access to the network plant to clients"""
    def __init__(self, loop, mqtt_host: str, mqtt_port: int,
                 config: Dict[str, Any]):
        self.plant = PlantBuilder().build(config, loop, mqtt_host, mqtt_port)

    def device_assemblies(self) -> Dict[str, DeviceAssembly]:
        """ Convenience accessor to devices. """
        return self.plant.device_assemblies

    def start(self):
        """ Convenience accessor to plant startup. """
        self.plant.start()
Пример #2
0
 async def test_can_build_float_sensor(self):
     """Test that a floating-point sensor can be built from a blueprint."""
     blueprint = {
         'sensor_1': {
             'type': 'sensor',
             'device_id': 'thermo',
             'config': {
                 'state.type': 'float',
                 'state.unit': 'F',
             },
         },
         'sensor_2': {
             'type': 'sensor',
             'device_id': 'thermo',
             'config': {
                 'state.type': 'float',
             },
         }
     }
     plant = PlantBuilder().build(blueprint, self.loop)
     self.assertEqual(3, len(plant.device_assemblies),
                      "Expected two devices + root to be built")
     self.assertEqual('F',
                      plant.device_assemblies['sensor_1'].device.state.unit,
                      "Expected a unit 'F'")
     self.assertIsInstance(plant.device_assemblies['sensor_1'].device.state,
                           FloatState, "Expected a floating point state")
     self.assertIsNone(
         plant.device_assemblies['sensor_2'].device.state.unit,
         "Unit should not exist")
     self.assertIsInstance(plant.device_assemblies['sensor_1'].device.state,
                           FloatState, "Expected a floating point state")
Пример #3
0
 async def test_can_build_single_node_with_single_device(self):
     """Can a basic node + device be built?"""
     blueprint = {
         'test_node': {
             'type': 'node',
             'device_id': 'test/ABC123',
             'devices': {
                 'test_switch': {
                     'type': 'basic_switch',
                     'device_id': 'switch',
                 }
             }
         }
     }
     plant = PlantBuilder().build(blueprint, self.loop)
     self.assertEqual(len(plant.device_assemblies), 3,
                      "Expected 3 device interfaces")
     root = plant.device_assemblies['root'].device
     self.assertEqual(len(root.sub_devices), 1,
                      "Expected one device at the root of the tree")
     self.assertIs(root.sub_devices['test_node'].__class__, NodeDevice,
                   "Top-level device should be a NodeDevice")
     node: NodeDevice = cast(NodeDevice, root.sub_devices['test_node'])
     self.assertEqual(node.device_id, 'test/ABC123',
                      "Expected 'test/ABC123' as device_id for node")
     self.assertEqual(len(node.sub_devices), 1, "Expected one sub-device")
     self.assertIn('test_switch', node.sub_devices,
                   "Expected test_switch sub-device key")
     sub_device: BasicSwitch = cast(BasicSwitch,
                                    node.sub_devices['test_switch'])
     self.assertIs(sub_device.__class__, BasicSwitch,
                   "Sub-device should be a BasicSwitch")
     self.assertEqual(sub_device.device_id, 'switch')
Пример #4
0
 async def test_receive_sensor_sample(self, mock_client):
     blueprint = {
         'test_node': {
             'type':      'node',
             'device_id': 'test/ABC123',
             'devices':   {
                 'test_sensor': {
                     'type':      'sensor',
                     'device_id': 'thermo',
                     'config': {
                         'state.type': 'float',
                         'state.unit': 'F'
                     }
                 }
             }
         },
         'test_node_2': {
             'type':      'node',
             'device_id': 'test/123ABC',
             'devices':   {
                 'test_switch': {
                     'type':      'basic_switch',
                     'device_id': 'switch',
                 },
                 'test_sensor': {
                     'type':      'sensor',
                     'device_id': 'thermo',
                     'config': {
                         'state.type': 'float',
                         'state.unit': 'F'
                     }
                 }
             }
         }
     }
     plant = PlantBuilder().build(blueprint, self.loop)
     await plant.upstream_source.queue.put({
         'topic': 'hausnet/test/ABC123/upstream',
         'message': '{"thermo":{"state":13}}'
     })
     await plant.upstream_source.queue.put({
         'topic': 'hausnet/test/ABC123/upstream',
         'message': '{"thermo":{"state":14}}'
     })
     plant.start()
     await plant.upstream_source.queue.join()
     plant.stop()
     assembly = plant.device_assemblies['test_node.test_sensor']
     queue = assembly.upstream_pipe.sink.queue
     self.assertEqual(
         {'state': 13},
         queue.get_nowait(),
         "Value of 13 expected from thermo device"
     )
     self.assertEqual(
         {'state': 14},
         queue.get_nowait(),
         "Value of 14 expected from thermo device"
     )
Пример #5
0
 async def test_send_state_change_to_switch(self, mock_client):
     """ Send a state change downstream. """
     blueprint = {
         'test_node': {
             'type':      'node',
             'device_id': 'test/ABC123',
             'devices':   {
                 'test_switch': {
                     'type':      'basic_switch',
                     'device_id': 'switch',
                 },
                 'test_sensor': {
                     'type':      'sensor',
                     'device_id': 'thermo',
                     'config': {
                         'state.type': 'float',
                         'state.unit': 'F'
                     }
                 }
             }
         },
         'test_node_2': {
             'type':      'node',
             'device_id': 'test/123ABC',
             'devices':   {
                 'test_switch': {
                     'type':      'basic_switch',
                     'device_id': 'switch',
                 },
                 'test_sensor': {
                     'type':      'sensor',
                     'device_id': 'thermo',
                     'config': {
                         'state.type': 'float',
                         'state.unit': 'F'
                     }
                 }
             }
         }
     }
     plant = PlantBuilder().build(blueprint, self.loop)
     assembly = plant.device_assemblies['test_node.test_switch']
     await assembly.client_in_queue.put({'state': OnOffState.ON})
     await assembly.client_in_queue.put({'state': OnOffState.OFF})
     plant.start()
     await assembly.client_in_queue.join()
     plant.stop()
     queue = plant.downstream_dest_queue
     self.assertEqual(
         {'topic': 'hausnet/test/ABC123/downstream', 'message': '{"switch":{"state":"ON"}}'},
         queue.sync_q.get_nowait(),
         "ON message to switch expected"
     )
     self.assertEqual(
         {'topic': 'hausnet/test/ABC123/downstream', 'message': '{"switch":{"state":"OFF"}}'},
         queue.sync_q.get_nowait(),
         "OFF message to switch expected"
     )
Пример #6
0
 async def test_switch_upstream_wiring_delivers(self):
     """Test that a basic switch state updates get delivered to the external world"""
     blueprint = {
         'test_node': {
             'type': 'node',
             'device_id': 'test/ABC123',
             'devices': {
                 'test_switch_1': {
                     'type': 'basic_switch',
                     'device_id': 'switch_1',
                 },
                 'test_switch_2': {
                     'type': 'basic_switch',
                     'device_id': 'switch_2',
                 }
             }
         }
     }
     plant = PlantBuilder().build(blueprint, self.loop)
     messages = [{
         'topic': 'hausnet/test/ABC123/upstream',
         'message': '{"switch_1": {"state": "OFF"}}'
     }, {
         'topic': 'hausnet/test/ABC123/upstream',
         'message': '{"switch_2": {"state": "ON"}}'
     }]
     out_messages = []
     in_queue = plant.upstream_src_queue.sync_q
     for message in messages:
         in_queue.put(message)
     plant.upstream_source.start()
     await plant.upstream_source.queue.join()
     plant.upstream_source.stop()
     out_messages.append(await
                         plant.device_assemblies['test_node.test_switch_1'].
                         upstream_pipe.sink.queue.get())
     plant.device_assemblies[
         'test_node.test_switch_1'].upstream_pipe.sink.queue.task_done()
     out_messages.append(await
                         plant.device_assemblies['test_node.test_switch_2'].
                         upstream_pipe.sink.queue.get())
     plant.device_assemblies[
         'test_node.test_switch_2'].upstream_pipe.sink.queue.task_done()
     self.assertEqual(
         plant.device_assemblies['test_node.test_switch_1'].device.state.
         value, OnOffState.OFF, "Expected switch 1 to be OFF")
     self.assertEqual(
         plant.device_assemblies['test_node.test_switch_2'].device.state.
         value, OnOffState.ON, "Expected switch 1 to be ON")
Пример #7
0
def command_loop():
    loop = asyncio.get_event_loop()
    up_stream = SyncToAsyncBufferedStream(loop)
    bundles = PlantBuilder(up_stream).build(conf.HAUSNET_CONFIG)
    mqtt_client = MqttClient(up_stream)

    async def sink_to_stdout(message):
        print(message)

    async def main():
        for name, device_bundle in bundles.items():
            await subscribe(device_bundle.upstream_pipe,
                            AsyncAnonymousObserver(sink_to_stdout))
        await mqtt_client._up_stream.stream()

    loop.run_until_complete(main())
    loop.close()
Пример #8
0
 async def test_switch_downstream_wiring_delivers(self):
     """Test that a basic switch state changes get delivered to the MQTT end of the stream"""
     blueprint = {
         'test_node': {
             'type': 'node',
             'device_id': 'test/ABC123',
             'devices': {
                 'test_switch': {
                     'type': 'basic_switch',
                     'device_id': 'switch_1',
                 },
             }
         }
     }
     plant = PlantBuilder().build(blueprint, self.loop)
     messages = [{'state': 'ON'}, {'state': 'OFF'}]
     out_messages = []
     source = plant.device_assemblies[
         'test_node.test_switch'].downstream_pipe.source
     in_queue = source.queue
     for message in messages:
         await in_queue.put(message)
     source.start()
     await source.queue.join()
     source.stop()
     out_queue = plant.downstream_dest_queue
     out_messages.append(out_queue.sync_q.get())
     out_messages.append(out_queue.sync_q.get())
     self.assertEqual(
         out_messages[0], {
             'topic': 'hausnet/test/ABC123/downstream',
             'message': '{"switch_1":{"state":"ON"}}'
         },
         "Expected an 'ON' JSON message on topic 'hausnet/test/ABC123/downstream'"
     )
     self.assertEqual(
         out_messages[1], {
             'topic': 'hausnet/test/ABC123/downstream',
             'message': '{"switch_1":{"state":"OFF"}}'
         },
         "Expected an 'OFF' JSON message on topic 'hausnet/test/ABC123/downstream'"
     )
Пример #9
0
 def __init__(self, loop, mqtt_host: str, mqtt_port: int,
              config: Dict[str, Any]):
     self.plant = PlantBuilder().build(config, loop, mqtt_host, mqtt_port)
Пример #10
0
 async def test_can_build_multiple_nodes_with_multiple_devices(self):
     """Can a set of basic nodes, each with multiple devices be built?"""
     blueprint = {
         'test_node_1': {
             'type': 'node',
             'device_id': 'test/ABC123',
             'devices': {
                 'test_switch_A': {
                     'type': 'basic_switch',
                     'device_id': 'switch_1',
                 },
                 'test_switch_B': {
                     'type': 'basic_switch',
                     'device_id': 'switch_2',
                 }
             }
         },
         'test_node_2': {
             'type': 'node',
             'device_id': 'test/ABC124',
             'devices': {
                 'test_switch_A': {
                     'type': 'basic_switch',
                     'device_id': 'switch_1',
                 },
                 'test_switch_B': {
                     'type': 'basic_switch',
                     'device_id': 'switch_2',
                 },
                 'test_switch_C': {
                     'type': 'basic_switch',
                     'device_id': 'switch_3',
                 },
             }
         }
     }
     plant = PlantBuilder().build(blueprint, self.loop)
     self.assertEqual(len(plant.device_assemblies), 8,
                      "Expected 8 device interfaces")
     root = plant.device_assemblies['root'].device
     self.assertEqual(len(root.sub_devices), 2,
                      "Expected two nodes at the root of the tree")
     node_1 = root.sub_devices['test_node_1']
     self.assertIs(node_1.__class__, NodeDevice,
                   "Top-level device #1 should be a NodeDevice")
     node_2 = root.sub_devices['test_node_2']
     self.assertIs(node_2.__class__, NodeDevice,
                   "Top-level device #2 should be a NodeDevice")
     node_1: NodeDevice = cast(
         NodeDevice, plant.device_assemblies['test_node_1'].device)
     self.assertEqual(node_1.device_id, 'test/ABC123',
                      "Expected 'test/ABC123' as device_id for node")
     node_2 = cast(NodeDevice,
                   plant.device_assemblies['test_node_2'].device)
     self.assertEqual(node_2.device_id, 'test/ABC124',
                      "Expected 'test/ABC124' as device_id for node")
     # Test sub-devices on node 1
     self.assertEqual(len(node_1.sub_devices), 2,
                      "Expected two sub-devices")
     self.assertIn('test_switch_A', node_1.sub_devices,
                   "Expected test_switch_A sub-device key")
     self.assertIn('test_switch_B', node_1.sub_devices,
                   "Expected test_switch_B sub-device key")
     sub_device: BasicSwitch = cast(BasicSwitch,
                                    node_1.sub_devices['test_switch_A'])
     self.assertIs(sub_device.__class__, BasicSwitch,
                   "Sub-device A should be a BasicSwitch")
     self.assertEqual(sub_device.device_id, 'switch_1',
                      "Sub-device A's ID should be switch_1")
     sub_device = cast(BasicSwitch, node_1.sub_devices['test_switch_B'])
     self.assertIs(sub_device.__class__, BasicSwitch,
                   "Sub-device B should be a BasicSwitch")
     self.assertEqual(sub_device.device_id, 'switch_2',
                      "Sub-device B's ID should be switch_2")
     # Test sub-devices on node B
     self.assertEqual(len(node_2.sub_devices), 3,
                      "Expected two sub-devices")
     self.assertIn('test_switch_A', node_2.sub_devices,
                   "Expected test_switch_A sub-device key")
     self.assertIn('test_switch_B', node_2.sub_devices,
                   "Expected test_switch_B sub-device key")
     self.assertIn('test_switch_C', node_2.sub_devices,
                   "Expected test_switch_C sub-device key")
     sub_device: BasicSwitch = cast(BasicSwitch,
                                    node_2.sub_devices['test_switch_A'])
     self.assertIs(sub_device.__class__, BasicSwitch,
                   "Sub-device A should be a BasicSwitch")
     self.assertEqual(sub_device.device_id, 'switch_1',
                      "Sub-device A's ID should be switch_1")
     sub_device = cast(BasicSwitch, node_2.sub_devices['test_switch_B'])
     self.assertIs(sub_device.__class__, BasicSwitch,
                   "Sub-device B should be a BasicSwitch")
     self.assertEqual(sub_device.device_id, 'switch_2',
                      "Sub-device B's ID should be switch_2")
     sub_device = cast(BasicSwitch, node_2.sub_devices['test_switch_C'])
     self.assertIs(sub_device.__class__, BasicSwitch,
                   "Sub-device C should be a BasicSwitch")
     self.assertEqual(sub_device.device_id, 'switch_3',
                      "Sub-device C's ID should be switch_3")