示例#1
0
    def test_database_output_plugin(self):
        """ Test that the DatabaseOutputPlugin works as expected. """
        plugin = monitor.DatabaseOutputPlugin(
            'sqlite://', interval=timedelta(seconds=1))  # # in-memory database
        plugin.initialise()

        example_400010_line = b'R 0.024: 400010010081013700180015001A000000000000400000 CRC=87'

        monitor.parse_line(example_400010_line, [plugin])
        with sql.session_scope(plugin.engine) as session:
            self.assertEqual(
                0,
                session.query(sql.P1P2State).count(),
                "Plugin should not write to database until 1 second after initialisation"
            )

        monitor.parse_line(example_400010_line, [plugin])
        with sql.session_scope(plugin.engine) as session:
            self.assertEqual(
                0,
                session.query(sql.P1P2State).count(),
                "Plugin should not write to database until 1 second after initialisation"
            )

        time.sleep(1)

        monitor.parse_line(example_400010_line, [plugin])
        with sql.session_scope(plugin.engine) as session:
            self.assertEqual(
                1,
                session.query(sql.P1P2State).count(),
                "Second line should write values accumulated during first round "
                "to the database")
            record = session.query(sql.P1P2State).one()
            self.assertEqual(55, record.target_dhw_temp)

        monitor.parse_line(example_400010_line, [plugin])
        with sql.session_scope(plugin.engine) as session:
            self.assertEqual(
                1,
                session.query(sql.P1P2State).count(),
                "Plugin should not write to database until 1 second after last write"
            )

        time.sleep(1)

        monitor.parse_line(example_400010_line, [plugin])
        with sql.session_scope(plugin.engine) as session:
            self.assertEqual(
                2,
                session.query(sql.P1P2State).count(),
                "Second line should write values accumulated during first round "
                "to the database")
示例#2
0
文件: poller.py 项目: qris/pytherma
def poll_once(daikin_interface, decoding_table, engine):
    """ Poll Daikin ASHP once for all known pages.

    Record their raw contents and decoded values in the database.
    """
    with session_scope(engine) as session:
        serial_state = SerialState(
            timestamp=datetime.datetime.now().astimezone(),
            raw_page_contents={},
            variable_values={})
        session.add(serial_state)

        for prefix in decoding_table:
            command_packet = bytes(prefix) + pytherma.comms.calculate_checksum(
                prefix)

            response_packet = pytherma.comms.execute_command(
                daikin_interface, command_packet)
            serial_state.raw_page_contents[prefix[2]] = list(
                response_packet[3:-1])

            values = decoding.decode_using_table(command_packet,
                                                 response_packet,
                                                 decoding_table)

            # JSON dict keys are always strings, so for the avoidance of doubt, we convert
            # the keys to strings here. https://stackoverflow.com/questions/1450957
            serial_state.variable_values.update({
                str(variable_id): _adapt_value_to_json(value[1])
                for variable_id, value in values.items()
            })
示例#3
0
    def test_poll_once(self):
        """ Test that poll_once() works as expected using built-in definitions. """
        simulator = DaikinSimulator()

        engine = sqlalchemy.create_engine('sqlite://')  # in-memory database
        sql.Base.metadata.create_all(engine)

        poller.poll_once(simulator, decoding.serial_page_prefix_to_decoders,
                         engine)

        with sql.session_scope(engine) as session:
            self.assertEqual(1, session.query(sql.SerialState).count())
            state = session.query(sql.SerialState).one()

            # The simulator returns a response at random when there's more than one, so choose
            # a value to which the response is always the same:
            self.assertEqual(0x2, state.variable_values['47'],
                             "Wrong decode for 47:O/U EEPROM (1st digit)")
            self.assertEqual(0x31, state.variable_values['48'],
                             "Wrong decode for 48:O/U EEPROM (3rd 4th digit)")
            self.assertEqual(0x95, state.variable_values['49'],
                             "Wrong decode for 49:O/U EEPROM (5th 6th digit)")
            self.assertEqual(0x1, state.variable_values['50'],
                             "Wrong decode for 50:O/U EEPROM (7th 8th digit)")
            self.assertEqual(0x2, state.variable_values['51'],
                             "Wrong decode for 51:O/U EEPROM (10th digit)")
            self.assertEqual(0x5, state.variable_values['52'],
                             "Wrong decode for 52:O/U EEPROM (11th digit)")
示例#4
0
    def handle_parsed_values(self, values, raw_record):
        """ Handle some values parsed by decode_p1p2, by collecting them ready to write to the database. """
        if self.record is None:
            self.record = P1P2State(raw_packets_contents={})

        # Store the most recent packet for each prefix in raw_packets_contents:
        packet_prefix = raw_record[:6]
        self.record.raw_packets_contents[packet_prefix] = raw_record

        for name, (decoder, value) in values.items():
            if name.value not in P1P2State.__mapper__.attrs:
                raise AttributeError(
                    f"{name} is not a valid attribute of P1P2State")

            setattr(self.record, name.value, value)

        time_now = datetime.datetime.now().astimezone()
        if time_now > self.next_write_time:
            # Write values collected so far to the database, and clear them.
            self.record.timestamp = time_now
            with session_scope(self.engine) as session:
                session.add(self.record)
            self.record = None
            self.next_write_time += self.interval
示例#5
0
    def test_espaltherma_definitions(self):
        """ Test that poll_once() works as expected using espaltherma definitions. """
        simulator = DaikinSimulator()

        definitions_file = os.path.join(DEFINITION_FILES,
                                        'ALTHERMA(LT_CA_CB_04-08KW).h')
        with open(definitions_file) as f:
            definition_text = f.read()
        espaltherma_decoding_table = parse_espaltherma_definition(
            definition_text, output_text=False)

        engine = sqlalchemy.create_engine('sqlite://')  # in-memory database
        sql.Base.metadata.create_all(engine)

        poller.poll_once(simulator, espaltherma_decoding_table, engine)

        with sql.session_scope(engine) as session:
            self.assertEqual(1, session.query(sql.SerialState).count())
            state = session.query(sql.SerialState).one()

            # The simulator returns a response at random when there's more than one, so choose
            # a value to which the response is always the same:
            self.assertEqual(6.0, state.variable_values['00.12.105'],
                             "21:O/U capacity (kW)")