I made a small coap sender since http client was too slow to be used on battery often.
It seems the UDP class cant take a hostname, so you have to find the ip first and store it in (fake)eeprom or similiar, or maybe your project can work with a statically programmed IP.
void coap_send(char* data)
{
Udp.beginPacket({1,2,3,4}, 5683);
uint8_t coapid = 1; //ideally this should be a unique id for each packet, but saving it in eeprom to survive a deep sleep seems a bit overkill
char tempbuf[400];
uint8_t p = 0;
// VVTTLLLL
tempbuf[p++] = 0b01010000; //V=01 T=01 (No confirm) 0 token length
tempbuf[p++] = 0b00000010; //0.2=POST req
tempbuf[p++] = (coapid & 0xFF00) >> 8; //Message id
tempbuf[p++] = (coapid & 0xff); //Message id 1
//tempbuf[p++] = 0xff; //no options
char host[13] = "hostname.dk";
//Option 3 - delta 3 - URI_Host
uint8_t hostlen = strlen(host);
if (hostlen > 12) //Hostname is limited to 99chars, so we dont need to support type 14
{
tempbuf[p++] = 0b00110000 | 13; //1101 = 13
tempbuf[p++] = hostlen - 13;
} else {
tempbuf[p++] = 0b00110000 | hostlen;
}
strncpy(&tempbuf[p], host, hostlen);
p += hostlen;
//Option 11 - delta 8 - URI_PATH - /incoming
//88 69 6e 63 6f 6d 69 6e 67
tempbuf[p++] = 0x88;
tempbuf[p++] = 0x69;
tempbuf[p++] = 0x6e;
tempbuf[p++] = 0x63;
tempbuf[p++] = 0x6f;
tempbuf[p++] = 0x6d;
tempbuf[p++] = 0x69;
tempbuf[p++] = 0x6e;
tempbuf[p++] = 0x67;
//Option 12 - delta 1 - format json
//11 32
tempbuf[p++] = 0x11;
tempbuf[p++] = 0x32;
tempbuf[p++] = 0xff; //end of options
strncpy(&tempbuf[p], data, strlen(data)); //would be better to send the 2 strings asis, but 2 calls to Udp.write seems to upset the node server, maybe a null char is being inserted.
Udp.write((uint8_t*)tempbuf, p+strlen(data));
Udp.endPacket();
}
Nodejs server to receive it, it checks the data is somewhat valid and then calls the same server over http with the data
const coap = require('coap')
, server = coap.createServer();
var http = require('http');
server.on('request', function(req, res) {
var url = req.url.split('/')[1];
// console.log(req.rsinfo.address+":"+req.rsinfo.port+" >> "+req.payload.toString('utf-8'));
if (url == "incoming")
{
var payload = req.payload.toString('utf-8');
try
{
var js = JSON.parse(payload.toString('utf-8'));
var version = js.v;
var id = js.id;
var sensors = js.sensors;
var url = "/incoming.php?v="+version+"&id="+id;
sensors.forEach(function (sensor) {
url += "&"+sensor.name+"="+sensor.value;
});
var options = {
host: 'hostname.dk',
path: url,
port: '80',
headers: {
'X-Forwarded-For': req.rsinfo.address,
'User-Agent': 'NodeJS CoAP proxy'
}
};
var httpreq = http.request(options, function(httpres) {
console.log(req.rsinfo.address+":"+req.rsinfo.port+" >> "+url);
});
httpreq.end();
} catch (ex) {
console.log("Json parse failed >> ",payload.toString('utf-8'),ex);
}
}
})
// the default CoAP port is 5683
server.listen(function() {
console.log("Server up ...");
})
Usage
sprintf(msg, "{\"id\":\"%s\",\"v\":1,\"sensors\":[{\"name\":\"temp\",\"value\":\"%0d.%d\"},{\"name\":\"hum\",\"value\":\"%0d.%d\"},{\"name\":\"dp\",\"value\":\"%0d.%d\"},{\"name\":\"hi\",\"value\":\"%0d.%d\"},{\"name\":\"ldr\",\"value\":\"%i\"},{\"name\":\"batt\",\"value\":\"%i\"},{\"name\":\"orgbatt\",\"value\":\"%i\"}]}",
id,(int)temp, temp1, (int)hum, temp2, (int)dp, temp3, (int)hi, temp4, ldr, batt, orgbatt);
coap_send(msg);