/** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. */ /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.thingml.networkplugins.c.arduino; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.sintef.thingml.Configuration; import org.sintef.thingml.ExternalConnector; import org.sintef.thingml.Message; import org.sintef.thingml.Port; import org.sintef.thingml.Protocol; import org.sintef.thingml.Thing; import org.sintef.thingml.helpers.AnnotatedElementHelper; import org.thingml.compilers.Context; import org.thingml.compilers.c.CCompilerContext; import org.thingml.compilers.c.CPluginHelper; import org.thingml.compilers.spi.NetworkPlugin; import org.thingml.compilers.spi.SerializationPlugin; /** * * @author sintef */ public class ESP8266MQTTPlugin extends NetworkPlugin { CCompilerContext ctx; public ESP8266MQTTPlugin() { super(); } public String getPluginID() { return "ESP8266MQTTPlugin"; } public List<String> getSupportedProtocols() { List<String> res = new ArrayList<>(); res.add("MQTT"); res.add("mqtt"); return res; } public List<String> getTargetedLanguages() { List<String> res = new ArrayList<>(); res.add("arduino"); return res; } public void generateMessageForwarders(StringBuilder builder, StringBuilder headerbuilder, Configuration cfg, Protocol prot) { try { final SerializationPlugin sp = ctx.getSerializationPlugin(prot); for (NetworkPlugin.ThingPortMessage tpm : getMessagesSent(cfg, prot)) { Thing t = tpm.t; Port p = tpm.p; Message m = tpm.m; builder.append("// Forwarding of messages " + prot.getName() + "::" + t.getName() + "::" + p.getName() + "::" + m.getName() + "\n"); builder.append("void forward_" + prot.getName() + "_" + ctx.getSenderName(t, p, m)); ctx.appendFormalParameters(t, builder, m); builder.append("{\n"); String i = sp.generateSerialization(builder, "forward_buf", m); builder.append("\n//Forwarding with specified function \n"); builder.append(prot.getName() + "_forwardMessage(forward_buf, " + i + ");\n"); builder.append("}\n\n"); headerbuilder.append("// Forwarding of messages " + prot.getName() + "::" + t.getName() + "::" + p.getName() + "::" + m.getName() + "\n"); headerbuilder.append("void forward_" + prot.getName() + "_" + ctx.getSenderName(t, p, m)); ctx.appendFormalParameters(t, headerbuilder, m); headerbuilder.append(";\n"); } } catch (UnsupportedEncodingException uee) { System.err.println("Could not get serialization plugin... Expect some errors in the generated code"); uee.printStackTrace(); return; } } public void generateNetworkLibrary(Configuration cfg, Context ctx, Set<Protocol> protocols) { this.ctx = (CCompilerContext) ctx; if(protocols.size() > 1) { System.out.println("[ERROR] More than one protocol UDP, this is not allowed for ESP8862UDPPlugin"); } else if(protocols.size() > 0) { Protocol protocol = protocols.iterator().next(); try { SerializationPlugin ser = ctx.getSerializationPlugin(protocol); Set<ExternalConnector> ecos = this.getExternalConnectors(cfg, protocol); if(!ecos.isEmpty()) { String ctemplate = ctx.getTemplateByID("templates/ESP8266MQTTPlugin.c"); String htemplate = ctx.getTemplateByID("templates/ESP8266MQTTPlugin.h"); String portName = protocol.getName(); for (ExternalConnector eco : ecos) { eco.setName(portName); } ctemplate = ctemplate.replace("/*PORT_NAME*/", portName); htemplate = htemplate.replace("/*PORT_NAME*/", portName); Integer remotePort; if (AnnotatedElementHelper.hasAnnotation(protocol, "mqtt_broker_port")) { remotePort = Integer.parseInt(AnnotatedElementHelper.annotation(protocol, "mqtt_broker_port").iterator().next()); } else { remotePort = 1883; } ctemplate = ctemplate.replace("/*BROKER_PORT*/", remotePort.toString()); String remoteAddress; if (AnnotatedElementHelper.hasAnnotation(protocol, "mqtt_broker_address")) { remoteAddress = AnnotatedElementHelper.annotation(protocol, "mqtt_broker_address").iterator().next(); } else { remoteAddress = "192.168.0.255"; } ctemplate = ctemplate.replace("/*BROKER_ADDRESS*/", remoteAddress); String ssid; if (AnnotatedElementHelper.hasAnnotation(protocol, "wifi_ssid")) { ssid = AnnotatedElementHelper.annotation(protocol, "wifi_ssid").iterator().next(); } else { ssid = "WIFI_SSID"; } ctemplate = ctemplate.replace("/*SSID*/", ssid); String wifiPassword; if (AnnotatedElementHelper.hasAnnotation(protocol, "wifi_password")) { wifiPassword = AnnotatedElementHelper.annotation(protocol, "wifi_password").iterator().next(); } else { wifiPassword = "WIFI_PASSWORD"; } ctemplate = ctemplate.replace("/*PASSWORD*/", wifiPassword); Set<Message> messages = new HashSet<>(); Integer maxMsgSize = 0; for (NetworkPlugin.ThingPortMessage tpm : getMessagesReceived(cfg, protocol)) { Message m = tpm.m; if (m != null) System.out.print("m: " + m.getName()); messages.add(m); if (this.ctx.getMessageSerializationSize(m) > maxMsgSize) { maxMsgSize = this.ctx.getMessageSerializationSize(m) - 2; } } ctemplate = ctemplate.replace("/*MAX_MSG_SIZE*/", maxMsgSize.toString());String sendTopic, receiveTopic; if (AnnotatedElementHelper.hasAnnotation(protocol, "mqtt_send_topic")) { sendTopic = AnnotatedElementHelper.annotation(protocol, "mqtt_send_topic").iterator().next(); } else if(AnnotatedElementHelper.hasAnnotation(protocol, "mqtt_topic")) { sendTopic = AnnotatedElementHelper.annotation(protocol, "mqtt_topic").iterator().next(); } else { sendTopic = "ThingML"; } if (AnnotatedElementHelper.hasAnnotation(protocol, "mqtt_receive_topic")) { receiveTopic = AnnotatedElementHelper.annotation(protocol, "mqtt_receive_topic").iterator().next(); } else if(AnnotatedElementHelper.hasAnnotation(protocol, "mqtt_topic")) { receiveTopic = AnnotatedElementHelper.annotation(protocol, "mqtt_topic").iterator().next(); } else { receiveTopic = "ThingML"; } if(!getMessagesReceived(cfg, protocol).isEmpty()) ctemplate = ctemplate.replace("/*SUB_TOPIC*/", receiveTopic); if(!getMessagesSent(cfg, protocol).isEmpty()) ctemplate = ctemplate.replace("/*PUB_TOPIC*/", sendTopic); String forward, parserCall; if(AnnotatedElementHelper.isDefined(protocol, "mqtt_escape_null", "true")) { forward = CPluginHelper.generateNullCharEscaperSend("msg", "size", "buf", "length", portName + "_ESCAPE_CHAR"); forward += " " + portName + "_client.publish(\"" + sendTopic + "\", buf, length);"; parserCall = CPluginHelper.generateNullCharEscaperReceive("payload", "length", "buf", "size", portName + "_ESCAPE_CHAR"); parserCall += " " + portName + "_parser(buf, size);"; } else { forward = " " + portName + "_client.publish(\"" + sendTopic + "\", msg, size);"; parserCall = " " + portName + "_parser(payload, length);"; } ctemplate = ctemplate.replace("/*FORWARD*/", forward); ctemplate = ctemplate.replace("/*PARSER_CALL*/", parserCall); String escapeByte; if (AnnotatedElementHelper.hasAnnotation(protocol, "mqtt_escape_byte")) { escapeByte = AnnotatedElementHelper.annotation(protocol, "mqtt_escape_byte").iterator().next(); } else { escapeByte = "125"; } ctemplate = ctemplate.replace("/*ESCAPE_CHAR*/", escapeByte); //Connector Instanciation StringBuilder eco_instance = new StringBuilder(); eco_instance.append("//Connector"); //De Serializer StringBuilder ParserImplementation = new StringBuilder(); ParserImplementation.append("void " + portName + "_parser(byte * msg, uint16_t size) {\n"); ser.generateParserBody(ParserImplementation, "msg", "size", messages, portName + "_instance.listener_id"); ParserImplementation.append("}\n"); ctemplate = ctemplate.replace("/*PARSER*/", ser.generateSubFunctions() + ParserImplementation); //End De Serializer ctemplate = ctemplate.replace("/*INSTANCE_INFORMATION*/", eco_instance); this.ctx.addToInitCode("\n" + portName + "_instance.listener_id = add_instance(&" + portName + "_instance);\n"); this.ctx.addToInitCode(portName + "_setup();\n"); this.ctx.addToPollCode(portName + "_read();\n"); StringBuilder b = new StringBuilder(); StringBuilder h = new StringBuilder(); generateMessageForwarders(b, h, cfg, protocol); ctemplate += b; htemplate += h; ctx.getBuilder(portName + ".c").append(ctemplate); ctx.getBuilder(portName + ".h").append(htemplate); } } catch (UnsupportedEncodingException ex) { Logger.getLogger(ESP8266MQTTPlugin.class.getName()).log(Level.SEVERE, null, ex); } } } }