def test_deepsleep(mocker, caplog): """ Check deepsleep behavior. """ # Acquire minimal settings. from test.settings import sleep as sleep_settings # Set deepsleep mode. sleep_settings.main['deepsleep'] = True # Invoke datalogger for a single duty cycle. datalogger = invoke_datalogger_pycom(caplog, settings=sleep_settings) # Patch machinery to mock the sleep method. import machine mocker.patch('machine.deepsleep', create=True) # Invoke sleep. datalogger.sleep() # Proof the "machine.deepsleep" function has been invoked. machine.deepsleep.assert_called_once() # Capture log output. captured = caplog.text # Proof it works by verifying log output. assert re.match('.*Entering deep sleep for .+ seconds.*', captured, flags=re.DOTALL), captured
def test_timesleep(mocker, caplog): """ Check normal "time.sleep()" behavior without any machine.sleep methods. """ # Acquire minimal settings. from test.settings import sleep as sleep_settings # Invoke datalogger for a single duty cycle. datalogger = invoke_datalogger_pycom(caplog, settings=sleep_settings) # Patch machinery to mock the sleep method. import time mocker.patch('time.sleep', create=True) # Invoke sleep. datalogger.sleep() # Proof the "time.sleep" function has been invoked. time.sleep.assert_called_once() # Capture log output. captured = caplog.text # Proof it works by verifying log output. assert re.match('.*Waiting for .+ seconds.*', captured, flags=re.DOTALL), captured
def test_uplink_system_temperature(network_lora, caplog): """ Pretend to invoke the datalogger on a LoPy4 with basic system sensors. Effectively, only the "system.temperature" sensor will be transmitted over LoRa telemetry. By intercepting the lora socket communication, proof that the submitted payload is correct by checking the raw payload value and decoding it through Cayenne. """ # Define artificial LoRa conversation. network_lora.register_conversation() # Invoke datalogger with LoRaWAN telemetry settings for a single duty cycle. from test.settings import telemetry_lorawan invoke_datalogger_pycom(caplog, settings=telemetry_lorawan) # Capture log output. captured = caplog.text # Proof it works by verifying log output. assert "Starting Terkin datalogger" in captured, captured assert "platform: LoPy4" in captured, captured assert "[LoRa] Starting LoRa Manager" in captured, captured assert "Telemetry transport: CayenneLPP over LoRaWAN/TTN" in captured, captured assert "Telemetry status: SUCCESS (1/1)" in captured, captured # Check the raw LoRa payload. from mocket import Mocket assert Mocket.last_request() == bytearray(b'\x00g\x01\xbf\x00\x01\x00') # Check the value after decoding from CayenneLPP. from cayennelpp import LppFrame data = LppFrame.from_bytes(Mocket.last_request()).data # System temperature assert data[0].channel == 0 assert data[0].type == 103 assert data[0].value == (44.7, ) # EOF? assert data[1].channel == 0 assert data[1].type == 1 assert data[1].value == (0, ) assert "[LoRa] No downlink message processed" in captured, captured
def test_downlink_unpause(network_lora, caplog): """ Simulate a downlink "unpause" command on LoRaWAN port 2. """ # Define artificial LoRa conversation. network_lora.register_conversation(response_port=2, response_data=[b'\x00']) # Invoke datalogger with LoRaWAN telemetry settings for a single duty cycle. from test.settings import telemetry_lorawan invoke_datalogger_pycom(caplog, settings=telemetry_lorawan) # Capture log output. captured = caplog.text # Proof it works by verifying log output. assert '[LoRa] Received "pause payload submission" command: False' in captured, captured
def test_downlink_interval_reset(network_lora, caplog): """ Simulate a downlink "reset interval" command on LoRaWAN port 1. """ # Define artificial LoRa conversation. network_lora.register_conversation(response_port=1, response_data=[b'\x00']) # Invoke datalogger with LoRaWAN telemetry settings for a single duty cycle. from test.settings import telemetry_lorawan invoke_datalogger_pycom(caplog, settings=telemetry_lorawan) # Capture log output. captured = caplog.text # Proof it works by verifying log output. assert '[LoRa] Received "reset deep sleep interval" command, erasing from NVRAM.' in captured, captured
def test_maintenance(mocker, caplog): """ Check maintenance mode. When the device is in maintenance mode, a different duty cycle will apply and the sleep method will resort to "time.sleep" in order to keep the appliance "online", even when deepsleep mode is enabled through the configuration. """ # Acquire minimal settings. from test.settings import sleep as sleep_settings # Set deepsleep mode. sleep_settings.main['deepsleep'] = True # Invoke datalogger for a single duty cycle. datalogger = invoke_datalogger_pycom(caplog, settings=sleep_settings) # Enable maintenance mode. datalogger.device.status.maintenance = True # Patch machinery to mock the sleep method. import time mocker.patch('time.sleep', create=True) # Invoke sleep. datalogger.sleep() # Proof the "time.sleep" function has been invoked. time.sleep.assert_called_once() # Capture log output. captured = caplog.text # Proof it works by verifying log output. assert re.match( '.*Device is in maintenance mode. Skipping deep sleep and adjusting sleep time to .+ seconds..*', captured, flags=re.DOTALL), captured assert re.match('.*Waiting for .+ seconds.*', captured, flags=re.DOTALL), captured
def test_sensors(mocker, caplog): """ Check the whole sensor machinery. """ # Acquire minimal settings. from test.settings import sensors_micropython as sensor_settings # Pretend the HX711 to be ready. mocker.patch('terkin.lib.hx711_heisenberg.HX711Heisenberg.is_ready', mock.Mock(return_value=True)) # Invoke datalogger for a single duty cycle. datalogger = invoke_datalogger_pycom(caplog, settings=sensor_settings) # Capture log output. captured = caplog.text # Proof it works by verifying log output. assert "Found 2 I2C devices: [118, 119]" in captured, captured assert "Found 2 1-Wire (DS18x20) devices: ['28ff641d8fdf18c1', '28ff641d8fc3944f']" in captured, captured # Get hold of the last reading. last_reading = datalogger.storage.last_reading # Proof it works by verifying last sensor readings. # ADC assert last_reading['system.voltage.battery'] == 4.2 # BME280 assert last_reading['temperature.0x77.i2c:0'] == 15.129645347595215 assert last_reading['humidity.0x77.i2c:0'] == 77.88673400878906 assert last_reading['pressure.0x77.i2c:0'] == 1055.163671875 # DS18B20 assert last_reading['temperature.28ff641d8fc3944f.onewire:0'] == 48.1875 assert last_reading['temperature.28ff641d8fdf18c1.onewire:0'] == 48.1875 # HX711 assert last_reading['weight.0'] == 3.845
def test_uplink_environmental_sensors(mocker, network_lora, caplog): """ Pretend to invoke the datalogger on a LoPy4 with environmental sensors. By intercepting the lora socket communication, proof that the submitted payload is correct by checking the raw payload value and decoding it through Cayenne. """ # Define artificial LoRa conversation. network_lora.register_conversation() # Mix together different settings. from test.settings import telemetry_lorawan from test.settings import sensors as sensor_settings mocker.patch('test.settings.telemetry_lorawan.sensors', sensor_settings.sensors) # Invoke datalogger with LoRaWAN telemetry settings for a single duty cycle. invoke_datalogger_pycom(caplog, settings=telemetry_lorawan) # Capture log output. captured = caplog.text # Proof it works by verifying log output. assert "Starting Terkin datalogger" in captured, captured assert "platform: LoPy4" in captured, captured assert "[LoRa] Starting LoRa Manager" in captured, captured assert "Telemetry transport: CayenneLPP over LoRaWAN/TTN" in captured, captured assert "Telemetry status: SUCCESS (1/1)" in captured, captured # Check the raw LoRa payload. from mocket import Mocket assert Mocket.last_request() == bytearray( b'\x00g\x01\xbf\x00\x03\x01\xa4\x00\x02\x01\x80\x01g\x01\xe1\x02g\x01\xe1' b'\x03g\x00\x97\x00s)7\x00h\x9b\x00\x01\x00') # Check the value after decoding from CayenneLPP. from cayennelpp import LppFrame data = LppFrame.from_bytes(Mocket.last_request()).data # System temperature assert data[0].channel == 0 assert data[0].type == 103 assert data[0].value == (44.7, ) # Voltage assert data[1].channel == 0 assert data[1].type == 3 assert data[1].value == (4.2, ) # Weight (kg) assert data[2].channel == 0 assert data[2].type == 2 assert data[2].value == (3.84, ) # DS18B20 temperature assert data[3].channel == 1 assert data[3].type == 103 assert data[3].value == (48.1, ) assert data[4].channel == 2 assert data[4].type == 103 assert data[4].value == (48.1, ) # BME280 temperature assert data[5].channel == 3 assert data[5].type == 103 assert data[5].value == (15.1, ) # BME280 pressure assert data[6].channel == 0 assert data[6].type == 115 assert data[6].value == (1055.1, ) # BME280 humidity assert data[7].channel == 0 assert data[7].type == 104 assert data[7].value == (77.5, ) # EOF? assert data[8].channel == 0 assert data[8].type == 1 assert data[8].value == (0, ) assert "[LoRa] No downlink message processed" in captured, captured