Nol.A SDK Library 26.11.2
For IoT System Software Development
Loading...
Searching...
No Matches
plm100s/PLS100W_AM1005-P-485/main.cpp
#include <cox.h>
#include <algorithm>
#include <LoRaMacKR920.hpp>
// #define SENSOR_TEST_MODE
nRF5xFlashPage configMemory(0x76000);
char keyBuf[128];
Timer timerKeyInput;
Timer am1005Timer;
LoRaMacKR920 LoRaWAN = LoRaMacKR920(SX1276);
struct {
uint8_t ip;
uint16_t co2;
uint16_t voc;
float humidity;
float temperature;
uint16_t pm1;
uint16_t pm2_5;
uint16_t pm10;
uint16_t voc_now_ref;
uint16_t voc_ref;
uint16_t voc_now;
uint16_t reserved;
uint16_t state;
} res;
int recv_flag = 0;
uint8_t msg_type = 0;
uint8_t msg_length = 0;
uint8_t msg_command = 0;
uint8_t msg_data[40];
uint8_t msg_checksum = 0;
uint8_t data_index = 0;
static uint8_t devEui[8];
static uint8_t appKey[16];
#define DE_RE GPIO7
static void rs485WriteMode(){
printf("writemode\r\n");
digitalWrite(DE_RE, HIGH);
Serial2.stopListening();
}
static void rs485ReadMode(){
printf("readmode\r\n");
Serial2.listen();
digitalWrite(DE_RE, LOW);
}
static void getAirInfo(void* data){
uint8_t request[5] = { 0x11 /* head */, 0x02 /* length */, 0x01 /* command */, 0x00 /* ip */, 0x00 };
request[4] = 256 - ((request[0] + request[1] + request[2] + request[3]) % 256);
rs485WriteMode();
Serial2.write(request, sizeof(request));
Serial2.flush();
rs485ReadMode();
}
static void decode_AM1005(){
res.ip = msg_data[0];
res.co2 = ((uint16_t) msg_data[1] << 8) | (uint16_t) msg_data[2];
res.voc = ((uint16_t) msg_data[3] << 8) | (uint16_t) msg_data[4];
res.humidity = (((uint16_t) msg_data[5] << 8) | (uint16_t) msg_data[6]) / 10.0;
res.temperature = ((((uint16_t) msg_data[7] << 8) | (uint16_t) msg_data[8]) / 10.0) - 50;
res.pm1 = ((uint16_t) msg_data[9] << 8) | (uint16_t) msg_data[10];
res.pm2_5 = ((uint16_t) msg_data[11] << 8) | (uint16_t) msg_data[12];
res.pm10 = ((uint16_t) msg_data[13] << 8) | (uint16_t) msg_data[14];
res.voc_now_ref = ((uint16_t) msg_data[15] << 8) | (uint16_t) msg_data[16];
res.voc_ref = ((uint16_t) msg_data[17] << 8) | (uint16_t) msg_data[18];
res.voc_now = ((uint16_t) msg_data[19] << 8) | (uint16_t) msg_data[20];
res.reserved = ((uint16_t) msg_data[21] << 8) | (uint16_t) msg_data[22];
res.state = msg_data[23];
printf("ip : %d co2: %d voc: %d H : %0.1f T : %0.1f PM1.0: %d PM2.5: %d PM10: %d VOC_NOW/REF: %d VOC_NOW: %d VOC_REF: %d RESERVED: %d STATE: %d\r\n",
res.ip, res.co2, res.voc, res.humidity, res.temperature, res.pm1, res.pm2_5, res.pm10, res.voc_now_ref, res.voc_ref, res.voc_now, res.reserved, res.state);
}
int check_checksum(){
uint8_t checksum = 0;
checksum += msg_type;
checksum += msg_length;
checksum += msg_command;
for (int i = 0 ; i < msg_length-1; i++){
checksum += msg_data[i];
}
checksum = (256 - checksum) % 256 ;
printf("checksum: %d , msg_checksum: %d\r\n",checksum, msg_checksum);
if (checksum == msg_checksum){
return 1;
} else{
return 0;
}
}
static void taskPeriodicSend(void *) {
LoRaMacFrame *f = new LoRaMacFrame(255);
if (!f || !f->buf) {
printf("* Out of memory\n");
return;
}
f->port = 1;
char stringvalue[150];
int abc = sprintf(stringvalue, "\"CO2\":%d,\"VOC\":%d,\"Humidity\":%0.1f,\"Temperature\":%0.1f,\"PM1.0\":%d,\"PM2.5\":%d,\"PM10\":%d", res.co2, res.voc, res.humidity, res.temperature, res.pm1, res.pm2_5, res.pm10);
strncpy((char *) f->buf, stringvalue,abc);
f->len = strlen((char *) f->buf);
/* Uncomment below lines to specify parameters manually. */
LoRaWAN.useADR = false;
f->numTrials = 1;
error_t err = LoRaWAN.send(f);
printf("* Sending periodic report (%p:%s (%u byte)): %d\n", f, f->buf, f->len, err);
if (err != ERROR_SUCCESS) {
delete f;
}
}
static void eventLoRaWANJoin(
bool joined,
const uint8_t *joinedDevEui,
const uint8_t *joinedAppEui,
const uint8_t *joinedAppKey,
const uint8_t *joinedNwkSKey,
const uint8_t *joinedAppSKey,
uint32_t joinedDevAddr,
const RadioPacket &frame,
uint32_t
) {
if (joined) {
printf("* Joined to the network!\n");
postTask(getAirInfo, nullptr);
am1005Timer.startPeriodic(5000);
} else {
printf("* Join failed. Retry to join\n");
LoRaWAN.beginJoining(devEui, appKey);
}
}
static void eventLoRaWANSendDone(LoRaMac &, LoRaMacFrame *frame) {
printf("* Send done(%d): [%p] destined for port[%u], Freq:%lu Hz, Power:%d dBm, # of Tx:%u, ",
frame->result, frame, frame->port, frame->freq, frame->power, frame->numTrials);
if (frame->modulation == Radio::MOD_LORA) {
const char *strBW[] = { "Unknown", "125kHz", "250kHz", "500kHz", "Unexpected value" };
if (frame->meta.LoRa.bw > 3) {
frame->meta.LoRa.bw = (Radio::LoRaBW_t) 4;
}
printf("LoRa, SF:%u, BW:%s, ", frame->meta.LoRa.sf, strBW[frame->meta.LoRa.bw]);
} else if (frame->modulation == Radio::MOD_FSK) {
printf("FSK, ");
} else {
printf("Unkndown modulation, ");
}
printf("UNCONFIRMED");
} else if (frame->type == LoRaMacFrame::CONFIRMED) {
printf("CONFIRMED");
} else if (frame->type == LoRaMacFrame::MULTICAST) {
printf("MULTICAST (error)");
} else if (frame->type == LoRaMacFrame::PROPRIETARY) {
printf("PROPRIETARY");
} else {
printf("unknown type");
}
printf(" frame\n");
if ( frame->result == RadioPacket::TOO_BIG){
printf("- TOO BIG\n");
}
delete frame;
}
static void eventLoRaWANReceive(LoRaMac &lw, const LoRaMacFrame *frame) {
printf("* Received:");
for (uint8_t i = 0; i < frame->len; i++) {
printf(" %02X", frame->buf[i]);
}
printf(" (");
frame->printTo(Serial);
printf(")\n");
if (
) {
// If there is no pending send frames, send an empty frame to ack or pull more frames.
LoRaMacFrame *emptyFrame = new LoRaMacFrame(0);
if (emptyFrame) {
error_t err = LoRaWAN.send(emptyFrame);
if (err != ERROR_SUCCESS) {
delete emptyFrame;
}
}
}
}
static void receivemsg(SerialPort &p) {
while (p.available() > 0){
uint8_t msg_byte = p.read();
switch (recv_flag){
case 0:
msg_type = msg_byte;
(msg_type == 0x16) ? recv_flag++ : recv_flag ;
break;
case 1:
msg_length = msg_byte; //packet length
recv_flag++;
break;
case 2:
msg_command = msg_byte;
recv_flag++;
break;
case 3:
msg_data[data_index] = msg_byte;
data_index++;
if (data_index == msg_length-1){
recv_flag++;
data_index = 0;
}
break;
case 4:
msg_checksum = msg_byte;
printf("type: %d, length: %d, command: %d, \r\n", msg_type, msg_length, msg_command);
printf("data: ");
for (int i = 0 ; i < msg_length-1; i++){
printf("0x%x ",msg_data[i]);
}
printf("checksum: %d\r\n", msg_checksum);
if (check_checksum()){
decode_AM1005();//message parsing function
#ifndef SENSOR_TEST_MODE
postTask(taskPeriodicSend,nullptr);
#endif
recv_flag = 0;
}else {
printf("checksum Error!\r\n");
recv_flag = 0;
}
break;
}
}
}
static void beginLoRaWAN(void *) {
LoRaWAN.begin();
LoRaWAN.onSendDone(eventLoRaWANSendDone);
LoRaWAN.onReceive(eventLoRaWANReceive);
LoRaWAN.onJoin(eventLoRaWANJoin);
LoRaWAN.setPublicNetwork(true);
LoRaWAN.beginJoining(devEui, appKey);
}
static void eventAppKeyInput(SerialPort &) {
uint8_t numOctets = strlen(keyBuf);
if (numOctets == 32) {
numOctets /= 2;
char strOctet[3];
for (uint8_t j = 0; j < numOctets; j++) {
strOctet[0] = keyBuf[2 * j];
strOctet[1] = keyBuf[2 * j + 1];
strOctet[2] = '\0';
appKey[j] = strtoul(strOctet, NULL, 16);
}
printf("* New AppKey:");
for (uint8_t j = 0; j < numOctets; j++) {
printf(" %02X", appKey[j]);
}
printf(" (%u byte)\n", numOctets);
configMemory.write(appKey, 0, numOctets);
postTask(beginLoRaWAN);
return;
} else {
printf("* HEX string length MUST be 32-byte.");
}
Serial.inputKeyboard(keyBuf, sizeof(keyBuf) - 1);
}
static void eventKeyInput(SerialPort &) {
timerKeyInput.stop();
while (Serial.available() > 0) {
Serial.read();
}
Serial.onReceive(eventAppKeyInput);
Serial.listen();
Serial.inputKeyboard(keyBuf, sizeof(keyBuf) - 1);
Serial.println(
"* Enter a new appKey as a hexadecimal string "
"[ex. 00112233445566778899aabbccddeeff]"
);
}
void setup() {
Serial.begin(115200);
Serial.printf("\n*** [PLS100W] AM1005-P-485 + LoRaWAN ***\n");
System.getEUI(devEui);
Serial.printf("* EUI: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
devEui[0], devEui[1], devEui[2], devEui[3], devEui[4], devEui[5], devEui[6], devEui[7]);
configMemory.read(appKey, 0, 16);
Serial.printf("* AppKey: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
appKey[0], appKey[1], appKey[2], appKey[3],
appKey[4], appKey[5], appKey[6], appKey[7],
appKey[8], appKey[9], appKey[10], appKey[11],
appKey[12], appKey[13], appKey[14], appKey[15]);
Serial.printf("* Last reset reason:0x%02X\n", System.getResetReason());
if (System.getResetReason() & (System.RESET_REASON_DOG | System.RESET_REASON_SREQ)) {
const McuARMCortexM::CoreRegisterDump *last = System.getLastCoreRegisterDump();
Serial.printf(" - R0: 0x%08lx, R1: 0x%08lx, R2: 0x%08lx, R3: 0x%08lx\n", last->r0, last->r1, last->r2, last->r3);
Serial.printf(" - R12: 0x%08lx, LR: 0x%08lx, PC: 0x%08lx, PSR: 0x%08lx\n", last->r12, last->lr, last->pc, last->psr);
}
pinMode(DE_RE, OUTPUT);
Serial2.begin(9600);
Serial2.onReceive(receivemsg);
rs485ReadMode();
am1005Timer.onFired(getAirInfo);
#ifdef SENSOR_TEST_MODE
am1005Timer.startPeriodic(5000);
#else
if (memcmp(appKey, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 16) == 0) {
/* The appKey is required to be entered by user.*/
eventKeyInput(Serial);
} else {
Serial.println("* Press any key to enter a new AppKey in 3 seconds...");
timerKeyInput.onFired(beginLoRaWAN);
timerKeyInput.startOneShot(3000);
Serial.onReceive(eventKeyInput);
}
#endif
}
LoRaWAN frame.
Definition LoRaMac.hpp:88
FrameType_t type
Frame type.
Definition LoRaMac.hpp:102
Radio::LoRaSF_t sf
송신시 사용할, 또는 수신시 사용된 spreading factor
Definition LoRaMac.hpp:189
int16_t power
송신시 사용할 Tx power table index (LoRaMac::MaxTxPower ~ LoRaMac::MinTxPower), 송신 완료 콜백시 출력 세기(단위: dBm) 또는...
Definition LoRaMac.hpp:146
Radio::LoRaBW_t bw
송신시 사용할, 또는 수신시 사용된 bandwidth
Definition LoRaMac.hpp:206
struct LoRaMacFrame::@024007217170142272131231362111253110374345035353::@215311014042340047327077224045033277162306213223 LoRa
modulation 이 Radio::MOD_LORA 인 경우 사용되는 변수
uint8_t numTrials
전송 횟수
Definition LoRaMac.hpp:116
union LoRaMacFrame::@024007217170142272131231362111253110374345035353 meta
변복조 방식에 대한 속성
@ MULTICAST
Definition LoRaMac.hpp:95
@ PROPRIETARY
Definition LoRaMac.hpp:96
@ UNCONFIRMED
Definition LoRaMac.hpp:93
@ CONFIRMED
Definition LoRaMac.hpp:94
uint8_t port
Port number.
Definition LoRaMac.hpp:107
대한민국 920~923MHz 대역을 사용하는 LoRaMac
Definition LoRaMacKR920.hpp:25
LoRaWAN 단말 장치들을 위한 MAC 프로토콜
Definition LoRaMac.hpp:253
bool useADR
ADR 사용여부를 설정합니다.
Definition LoRaMac.hpp:442
bool framePending
Frame pending.
Definition LoRaMac.hpp:464
virtual error_t begin(uint8_t(*getBatteryLevel)()=NULL)
LoRaMAC layer initialization.
virtual error_t beginJoining(const uint8_t *devEui, const uint8_t *appEui, const uint8_t *appKey)
Over-the-Air Activation (OTAA) 방식의 join을 시도합니다.
void onJoin(void(*func)(LoRaMac &mac, bool result, const uint8_t *devEui, const uint8_t *appEui, const uint8_t *appKey, const uint8_t *nwkSKey, const uint8_t *appSKey, uint32_t devAddr, const RadioPacket &frame, uint32_t airTime))
Join이 완료되었을 때 호출될 콜백함수를 지정합니다.
void onSendDone(void(*sendDoneHandler)(LoRaMac &, LoRaMacFrame *))
전송이 완료될 때 호출될 함수를 지정합니다.
void setPublicNetwork(bool enable)
공용 LoRaWAN 네트워크를 사용할지 설정합니다.
void onReceive(void(*receiveHandler)(LoRaMac &radio, const LoRaMacFrame *frame))
수신이 완료될 때 호출될 함수를 지정합니다.
error_t send(LoRaMacFrame *frame)
frame 을 전송합니다.
uint8_t getNumPendingSendFrames()
전송 대기 중인 프레임 갯수를 구합니다.
무선 패킷
Definition RadioPacket.hpp:59
Radio::Modulation_t modulation
송신시 사용할, 또는 수신시 사용된 변복조 방식
Definition RadioPacket.hpp:160
uint32_t freq
송신시 사용할, 또는 수신시 사용된 주파수 (단위: Hz)
Definition RadioPacket.hpp:143
@ TOO_BIG
프레임이 너무 커서 전송 불가
Definition RadioPacket.hpp:94
Result_t result
송신 또는 수신 패킷 처리 결과
Definition RadioPacket.hpp:131
시리얼 포트를 제어하기 위한 클래스
Definition SerialPort.hpp:76
virtual int read()
포트 내부 버퍼에 수신된 문자를 하다 꺼냅니다.
virtual int available()
포트 내부 수신버퍼에 수신된 문자의 갯수를 반환합니다.
Timer는 일정 시간 이후에 1회 실행될 작업, 매 일정 시간마다 실행될 작업 등을 위한 기능입니다.
Definition Timer.hpp:61
void stop()
예약된, 혹은 측정 중인 Timer를 중단합니다.
bool startOneShot(uint32_t millis, bool interrupt=false)
작업함수를 millis 밀리초 이후 1회 실행합니다.
bool startPeriodic(uint32_t millis, bool interrupt=false)
작업함수를 매 millis 밀리초 주기로 반복하여 실행합니다.
void onFired(void(*func)(void *), void *args=nullptr)
타이머 만료시 실행시킬 작업함수를 지정합니다.
nRF5x MCU 내부 플래시 페이지에 데이터를 읽고 쓰기 위한 클래스
Definition nRF5xFlashPage.hpp:54
API and definitions.
@ ERROR_SUCCESS
Definition nola-common.h:119
bool digitalWrite(int8_t pin, int value)
pin 를 HIGH 또는 LOW 로 설정합니다.
bool pinMode(int8_t pin, enum ioDirection direction)
pin 을 direction 방향을 갖는 디지털 핀으로 동작하도록 설정합니다.
@ OUTPUT
Definition nola-common.h:383
SerialPort & Serial2
bool postTask(void(*func)(void *), void *args)
작업을 나중에 실행되도록 게시합니다.
nRF5x flash page
LoRaBW_t
LoRa Bandwidth Type.
Definition Radio.hpp:107
@ BW_125kHz
Definition Radio.hpp:109
@ MOD_FSK
Definition Radio.hpp:67
@ MOD_LORA
Definition Radio.hpp:68
@ SF7
Definition Radio.hpp:82
Definition McuARMCortexM.hpp:62