Home Forum Software Direct data access

Viewing 1 post (of 1 total)
  • Author
    Posts
  • #6763
    Radu
    Keymaster

    Direct data access is possible, although not recommended, because doing so, you loose the compensation layer implemented on the uRADMonitor server, that does post processing on the data before offering it via the API. On LoRaWAN systems, the payload is already present on the Network server and some of you are interested in how to access it from there, directly. On non-LoRaWAN systems you can change the “server” and “script” fields presented with USB command “getsettings” to change the backend and handle the data directly.

    See:
    https://www.uradmonitor.com/wordpress/wp-content/uploads/2019/01/uRADMonitor_LoraWAN_callback_config_v3_comp.pdf
    https://www.uradmonitor.com/wordpress/wp-content/uploads/2019/01/uRADMonitor_server_specs_02_comp.pdf

    But again, if you go this way, your readings might be inaccurate as you drop the uRADMonitor compensation layer implemented on the data server.
    First you need to disable the encryption. Connect the unit via USB, baudrate 9600, and issue the command “encrypt”,”0”

    Next, your payload will sent as decrypted.

    The INDUSTRIAL data structure (hardware HW105/HW106) , in ORDER, is as follows:
    `DeviceID 4B
    HardwareVersion 2B
    SoftwareVersion 2B
    Timestamp 4B
    Temperature 2B
    Pressure 2B
    Humidity 2B
    VOC 4B
    Noise 2B
    GasSensorTypeMask 1B
    Gas1 2B
    Gas2 2B
    Gas3 2B
    Gas4 2B
    PM1 2B
    PM2.5 2B
    PM10 2B
    CRC 4B`

    The A3 (hardware version HW107/HW108) is similar:
    `DeviceID 4B
    HardwareVersion 2B
    SoftwareVersion 2B
    Timestamp 4B
    Temperature 2B
    Pressure 2B
    Humidity 2B
    VOC 4B
    Noise 2B
    CO2 2B
    Formaldehyde 2B
    OZone 2B
    Reserved 4B
    PM1 2B
    PM2.5 2B
    PM10 2B
    CRC 4B`

    The CRC must be computed on the entire array, up until the CRC itself (so including last pm10 field, but not the following CRC).

    
    uint32_t crc32(uint8_t *buffer, uint16_t length, uint32_t seed = 0xFFFFFFFFUL);
    
    uint32_t crc32(uint8_t *buffer, uint16_t length, uint32_t seed) {
    	uint32_t crc = seed;
    	uint16_t i, j;
    	for (i=0; i<length; i++) {
            crc = crc ^ *(buffer++);
    		for (j=0; j<8; j++) {
    			if (crc & 1)
    		        crc = (crc>>1) ^ 0xEDB88320UL ;
    			else
    		        crc = crc >>1 ;
            }
        }
    	return crc ^ 0xFFFFFFFFUL;
    }

    Here’s how to decode A3 data in PHP:

    <?php 
    	// an uint16_t stores 16 bits, we use first bit for sign, and following 15 bits for number (0..32767)
    	// result is divided by 100 for a real with 2 decimals, max is 327.00
    	function UINT16ToDouble($val) {
    		$val = hexdec($val); //careful with input!
    		$res = 0;
    		$mask = 1<<15;
    		if ($val & $mask) {
    			$val &= ~$mask;
    			$res = -$val;
    		} else
    			$res = $val;
    		$res /= 100.0;
    		return $res;
    	}
    	function getAltitude($pressure) {
    		if ($pressure == 0 || $pressure == '' || $pressure == NULL || $pressure <= 65535) return NULL;
    		$alt = (1 - (pow($pressure / 101325, 0.1903))) / 0.0000225577;
    		return $alt;
    	}
    
    	$data = 'ggABsABsAD4AAAOECauF3hYBAAMkEhEBAp0AIQApAAAABAAGAAZY+/7/';
    
    	$decodedString = (string) bin2hex(base64_decode($data));
    
    	echo "Actual payload in uRADMonitor E7 format:".$decodedString;
    
    	// decoding E8
    	$fields = array();
    
    	$fields["versionhw"] = hexdec(substr($decodedString, 8, 4));
    	$fields["versionsw"] = hexdec(substr($decodedString, 12, 4));
    	$fields["timelocal"] = hexdec(substr($decodedString, 16, 8));
    	$fields["temperature"] = UINT16ToDouble(substr($decodedString, 24, 4));
    	$fields["pressure"] = hexdec(substr($decodedString, 28, 4)) + 65535;
    	$fields["altitude"] = getAltitude($fields["pressure"]);
    	$fields["humidity"] = UINT16ToDouble(substr($decodedString, 32, 4));			
    	$fields["voc"] = hexdec(substr($decodedString, 36, 8));
    	$fields["noise"] = UINT16ToDouble(substr($decodedString, 44, 4));  
    	// ID takes first 4 bytes, we have it already
    	$fields["co2"] = hexdec(substr($decodedString, 48, 4));
    	$fields["ch2o"] = hexdec(substr($decodedString, 52, 4));
        $fields["o3"] = hexdec(substr($decodedString, 56, 4));
        $fields["pm1"] = hexdec(substr($decodedString, 64, 4));
        $fields["pm25"] = hexdec(substr($decodedString, 68, 4));
        $fields["pm10"] = hexdec(substr($decodedString, 72, 4));	
    
        echo "<br>decode results:<br>";
        print_r($fields);
    ?>
Viewing 1 post (of 1 total)
  • You must be logged in to reply to this topic.