Cara subscribe dan publish mqtt menggunakan node-red


Ok kali ini saya akan membagikan cara bagaimana pubsub (publish dan subscribe) di node-red, pertama tama pastikan node-red sudah terinstall kalau belum terinstall coba buka postingan saya dibawah tentang bagaimana cara install node-red di raspberry pi.

Langkah pertama buka browser kalian dan jalankan http://localhost:1880 kalau kalian menjalankannya didalam raspberry pi, kalau remote tinggal masukkan ip raspberry pi diikuti dengan portnya misalkan jadinya http://192.168.0.3:1880 cara mengetahui ip raspberry pi kalian berapa coba jalankan ifconfig di terminal, nanti kalian bisa menemukan ip kalian disana.

Ok setelah terbuka node-red maka akan menampilkan seperti dibawah ini

Screenshot from 2019-11-01 09-57-33

setelah itu kita install mqtt plugin di node-red dengan cara buka manage pallete didalam menu ( garis 3 = ) dibagian atas lihat gambar dibawah

Screenshot from 2019-11-01 09-59-48

setelah terbuka maka masuk ke pallete install lalu masukkan mqtt di search dan install node-red-contrib-mqtt-broker

Screenshot from 2019-11-01 10-01-45

Tunggu beberapa saat sampai terinstall selanjutnya kembali ke halaman depan dan ketikkan mqtt di filter nodes, maka plugin mqtt sudah terinstall.

Screenshot from 2019-11-01 10-03-12

Cara menggunakan plugin ini adalah dengan cara drag n drop ke dalam Flow, kalau kita  perhatian ada dua macam nodes yaitu mqtt in dan mqtt out mqtt in artinya kita subscribe ke topik apabila mqtt out maka kita publish ke mqtt broker.

Ok langkah selanjutnya adalah pastikan kalian menginstall mqtt broker kalau belum silahkan lihat postingan sebelum ini mengenai cara menginstall mqtt di raspberry pi, detailnya howto nya silahkan lihat video dibawah

untuk alamat ip di mosquitto server saya menggunakan 10.81.141.48 kalau di tempat kalian bisa menggunakan ip kalian masing masing atau bisa juga localhost kalau kalian menjalankannya langsung di raspberry pi.

Demikian tutorial ini semoga bermanfaat

Happy Coding …

Salam ngoprek …

Setting raspberry pi sebagai mqtt server


Raspberry pi komputer mini SBC ini memiliki banyak kelebihan selain dikarenakan bentuknya yang kecil juga specnya juga lumayan untuk menjalankan beberapa aplikasi sederhana.

Kali ini saya akan memberikan tutorial mengenai cara menyiapkan raspberry pi untuk mqtt server, saya tidak akan membahas bagaimana cara menginstall OS di raspberry pi, harapannya raspberry pi kalian sudah bisa terhubung dengan internet sehingga kita bisa mendownload beberapa aplikasi untuk menjalankan mqtt server di raspberry pi, oh iya sebagai tambahan saya menggunakan raspbian sebagai OS.

OK langkah pertama adalah standard menjalankan update dan upgrade raspbian dengan cara

sudo apt update && sudo apt upgrade -y

setelah selesai maka langkah selanjutnya adalah install mosquitto broker

sudo apt install -y mosquitto mosquitto-clients

Setelah selesai supaya mosquittonya jalan secara otomatis pada saat restart atau raspberry pi dijalankan maka jalankan perintah dibawah ini

sudo systemctl enable mosquitto.service

Done selesai untuk mencoba nya kita bisa test dengan mengirim perintah via terminal untuk mengetest apakah mosquitto sudah jalan dengan cara sebagai berikut.

Continue reading “Setting raspberry pi sebagai mqtt server”

Payload decoder adeunis field tester


function Decode( fPort, bytes )
{

// Functions
function parseCoordinate( raw_value, coordinate )

{

// This function parses a coordinate payload part into

// dmm and ddd

var raw_itude = raw_value;

var temp = "";


// Degree section

var itude_string = ( (raw_itude >> 28) & 0xF ).toString( );

raw_itude <<= 4;


itude_string += ( (raw_itude >> 28) & 0xF ).toString( );

raw_itude <<= 4;


coordinate.degrees += itude_string;

itude_string += "°";


// Minute section

temp = ( (raw_itude >> 28) & 0xF ).toString( );

raw_itude <<= 4;


temp += ( (raw_itude >> 28) & 0xF ).toString( );

raw_itude <<= 4;

itude_string += temp;

itude_string += ".";

coordinate.minutes += temp;


// Decimal section

temp = ( (raw_itude >> 28) & 0xF ).toString( );

raw_itude <<= 4;


temp += ( (raw_itude >> 28) & 0xF ).toString( );

raw_itude <<= 4;


itude_string += temp;

coordinate.minutes += ".";

coordinate.minutes += temp;

return itude_string;

}

function parseLatitude( raw_latitude, coordinate )

{

var latitude = parseCoordinate( raw_latitude, coordinate );

latitude += ((raw_latitude & 0xF0) >> 4).toString( );

coordinate.minutes += ((raw_latitude & 0xF0) >> 4).toString( );


return latitude;

}

function parseLongitude( raw_longitude, coordinate )

{

var longitude = ( ((raw_longitude >> 28) & 0xF ) ).toString( );

coordinate.degrees = longitude;

longitude += parseCoordinate( raw_longitude << 4, coordinate );


return longitude;

}

function addField( field_no, payload )

{

switch( field_no )

{

// Presence of temperature information

case 0:

payload.temperature = bytes[bytes_pos_] & 0x7F;

// Temperature is negative

if( (bytes[bytes_pos_] & 0x80) > 0 )

{

payload.temperature -= 128;

}

bytes_pos_++;

break;

// Transmission triggered by the accelerometer

case 1:

payload.trigger = "accelerometer";

break;

// Transmission triggered by pressing pushbutton 1

case 2:

payload.trigger = "pushbutton";

break;

// Presence of GPS information

case 3:

// GPS Latitude

// An object is needed to handle and parse coordinates into ddd notation

var coordinate = {};

coordinate.degrees = "";

coordinate.minutes = "";


var raw_value = 0;

raw_value |= bytes[bytes_pos_++] << 24;

raw_value |= bytes[bytes_pos_++] << 16;

raw_value |= bytes[bytes_pos_++] << 8;

raw_value |= bytes[bytes_pos_++];


payload.lati_hemisphere = (raw_value & 1) == 1 ? "South" : "North";

payload.latitude_dmm = payload.lati_hemisphere.charAt( 0 ) + " ";

payload.latitude_dmm += parseLatitude( raw_value, coordinate );

payload.latitude = ( parseFloat( coordinate.degrees ) + parseFloat( coordinate.minutes ) / 60 ) * ( (raw_value & 1) == 1 ? -1.0 : 1.0);


// GPS Longitude

coordinate.degrees = "";

coordinate.minutes = "";

raw_value = 0;

raw_value |= bytes[bytes_pos_++] << 24;

raw_value |= bytes[bytes_pos_++] << 16;

raw_value |= bytes[bytes_pos_++] << 8;

raw_value |= bytes[bytes_pos_++];


payload.long_hemisphere = (raw_value & 1) == 1 ? "West" : "East";

payload.longitude_dmm = payload.long_hemisphere.charAt( 0 ) + " ";

payload.longitude_dmm += parseLongitude( raw_value, coordinate );

payload.longitude = ( parseFloat( coordinate.degrees ) + parseFloat( coordinate.minutes ) / 60 ) * ( (raw_value & 1) == 1 ? -1.0 : 1.0);


// GPS Quality

raw_value = bytes[bytes_pos_++];


switch( (raw_value & 0xF0) >> 4 )

{

case 1:

payload.gps_quality = "Good";

break;

case 2:

payload.gps_quality = "Average";

break;

case 3:

payload.gps_quality = "Poor";

break;

default:

payload.gps_quality = (raw_value >> 4) & 0xF;

break;

}

payload.hdop = (raw_value >> 4) & 0xF;


// Number of satellites

payload.sats = raw_value & 0xF;


break;

// Presence of Uplink frame counter

case 4:

payload.ul_counter = bytes[bytes_pos_++];

break;

// Presence of Downlink frame counter

case 5:

payload.dl_counter = bytes[bytes_pos_++];

break;

// Presence of battery level information

case 6:

payload.battery_level = bytes[bytes_pos_++] << 8;

payload.battery_level |= bytes[bytes_pos_++];

break;

// Presence of RSSI and SNR information

case 7:

// RSSI

payload.rssi_dl = bytes[bytes_pos_++];

payload.rssi_dl *= -1;


// SNR

payload.snr_dl = bytes[bytes_pos_] & 0x7F;

if( (bytes[bytes_pos_] & 0x80) > 0 )

{

payload.snr_dl -= 128;

}

bytes_pos_++;

break;

default:

// Do nothing

break;

}

}


// Declaration & initialization

var status_ = bytes[0];

var bytes_len_ = bytes.length;

var bytes_pos_ = 1;

var i = 0;

var payload = {};


// Get raw payload

var temp_hex_str = ""

payload.payload = "";

for( var j = 0; j < bytes_len_; j++ )

{

temp_hex_str = bytes[j].toString( 16 ).toUpperCase( );

if( temp_hex_str.length == 1 )

{

temp_hex_str = "0" + temp_hex_str;

}

payload.payload += temp_hex_str;

}


// Get payload values

do

{

// Check status, whether a field is set

if( (status_ & 0x80) > 0 )

{

addField( i, payload );

}

i++;

}

while( ((status_ <<= 1) & 0xFF) > 0 );


return payload;

}

Parsing data from mqtt ttn


Postingan kali ini adalah lanjutan dari postingan saya sebelumnya disini , nah pada postingan saya kali ini akan membahas bagaimana cara memparsing data json yang kita dapat dari ttn kemudian menampilkannya ke dalam dashboard, sehingga hasilnya seperti dibawah ini

[{"id":"1f1f6ed1.81cf91","type":"mqtt in","z":"7609c47a.c51b3c","name":"","topic":"+/devices/+/up","qos":"2","broker":"7833904b.af11d","x":220,"y":200,"wires":[["d839d790.4b77c8"]]},{"id":"d839d790.4b77c8","type":"json","z":"7609c47a.c51b3c","name":"","property":"payload","action":"obj","pretty":true,"x":470,"y":200,"wires":[["e2efc94c.1de158","47698174.a787f","9db17467.71c868","b38807c2.074058","6cc7cd06.b7c634"]]},{"id":"e2efc94c.1de158","type":"function","z":"7609c47a.c51b3c","name":"battery","func":"var obj = msg.payload;\nmsg.payload = obj.payload_fields.analog_in_3;\nreturn msg;","outputs":1,"noerr":0,"x":720,"y":180,"wires":[["9ea82fec.53c49"]]},{"id":"47698174.a787f","type":"function","z":"7609c47a.c51b3c","name":"temperature","func":"var obj = msg.payload;\nmsg.payload = obj.payload_fields.temperature_1;\nreturn msg;","outputs":1,"noerr":0,"x":710,"y":240,"wires":[["491b941b.7cb80c"]]},{"id":"9db17467.71c868","type":"function","z":"7609c47a.c51b3c","name":"humidity","func":"var obj = msg.payload;\nmsg.payload = obj.payload_fields.relative_humidity_2;\nreturn msg;","outputs":1,"noerr":0,"x":700,"y":300,"wires":[["754ca03c.46161"]]},{"id":"491b941b.7cb80c","type":"ui_chart","z":"7609c47a.c51b3c","name":"","group":"7fb7eee3.fc934","order":1,"width":0,"height":0,"label":"Temperature","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"86400","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":930,"y":240,"wires":[[],[]]},{"id":"9ea82fec.53c49","type":"ui_gauge","z":"7609c47a.c51b3c","name":"","group":"d98f26c6.56b8b8","order":1,"width":0,"height":0,"gtype":"gage","title":"Battery","label":"units","format":"{{value}}","min":0,"max":10,"colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":920,"y":180,"wires":[]},{"id":"754ca03c.46161","type":"ui_chart","z":"7609c47a.c51b3c","name":"","group":"7fb7eee3.fc934","order":2,"width":0,"height":0,"label":"Humidity","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"86400","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":920,"y":300,"wires":[[],[]]},{"id":"b38807c2.074058","type":"function","z":"7609c47a.c51b3c","name":"rssi","func":"var obj = msg.payload;\nmsg.payload = obj.metadata.gateways[0].rssi;\nreturn msg;","outputs":1,"noerr":0,"x":690,"y":360,"wires":[["9e68c3c6.729e5"]]},{"id":"9e68c3c6.729e5","type":"ui_chart","z":"7609c47a.c51b3c","name":"","group":"9a2e91ee.5594a","order":2,"width":0,"height":0,"label":"RSSI","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"86400","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":910,"y":360,"wires":[[],[]]},{"id":"6cc7cd06.b7c634","type":"function","z":"7609c47a.c51b3c","name":"rssi","func":"var obj = msg.payload;\nmsg.payload = obj.metadata.gateways[0].snr;\nreturn msg;","outputs":1,"noerr":0,"x":690,"y":420,"wires":[["c2e09073.55f99"]]},{"id":"c2e09073.55f99","type":"ui_chart","z":"7609c47a.c51b3c","name":"","group":"9a2e91ee.5594a","order":3,"width":0,"height":0,"label":"SNR","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"86400","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":910,"y":420,"wires":[[],[]]},{"id":"7833904b.af11d","type":"mqtt-broker","z":"","name":"application_name","broker":"asia-se.thethings.network","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"7fb7eee3.fc934","type":"ui_group","z":"","name":"Chart","tab":"5d83a158.d5268","order":2,"disp":true,"width":"6","collapse":false},{"id":"d98f26c6.56b8b8","type":"ui_group","z":"","name":"Gauge","tab":"5d83a158.d5268","order":1,"disp":true,"width":"6","collapse":false},{"id":"9a2e91ee.5594a","type":"ui_group","z":"","name":"Others","tab":"5d83a158.d5268","order":3,"disp":true,"width":"6","collapse":false},{"id":"5d83a158.d5268","type":"ui_tab","z":"","name":"Home","icon":"timeline"}]

TTN payload format for Rising HF RHF1S001


function Decoder(bytes, port) {
var obj = new Object();

//temp
var tempEncoded=(bytes[2]<<8)|(bytes[1]);
var tempDecoded=(tempEncoded*175.72/65536)-46.85;
obj.temp=tempDecoded.toFixed(2);

//humidity
var humEncoded=(bytes[3]);
var humDecoded=(humEncoded*125/256)-6;
obj.hum=humDecoded.toFixed(2);

//period
var periodEncoded=(bytes[5]<<8)|(bytes[4]);
var periodDecoded=(periodEncoded*2);
obj.period=periodDecoded+" sec";

//battery
var batteryEncoded=(bytes[8]);
var batteryDecoded=(batteryEncoded+150)*0.01;
obj.battery=batteryDecoded.toFixed(2);


return obj;
}

lora mini dev and ttn


lora_mini_devKali ini nyobain lora module buatan dragino namanya lora mini dev, uniknya dari module ini adalah sudah jadi satu antara RF dan mikro kontrollernya, untuk programmingnya sendiri cukup mudah karena sudah ada usb nya jadi tinggal colok aja mikro usb bawaannya terus bisa diprogram menggunakan arduino ide.

Reviewnya menyusul ya ini tadi baru  test OTAA ke thethingsnetwork si lancar jaya cuman awalnya sempat bingung untuk pin mapping lmicnya, soalnya nyari nyari didokumentasinya ngga nemu.

Beruntung banget pas lagi browsing nemu, nah dibawah ini adalah pinout mappingnya karena kalau pinout ini salah dijamin lora mini dev ini ngga akan bekerja di lmic

 const lmic_pinmap lmic_pins = {
 .nss = 10,
 .rxtx = LMIC_UNUSED_PIN,
 .rst = 9,
 .dio = {2, 6, 7},
};

Silahkan yang pingin nyoba nyoba ini modul bisa pake lmic standard tinggal nanti menyesuaikan lmicnya seperti diatas.

kalau mau liat2 codingannya ke github saya disini tinggal ganti lmicnya seperti diatas

Happy Coding ..

Salam ngoprek …