impAccelerator: Fieldbus Gateway


#1

Hi, i need develop a device that can read a web page table and send this info by modbus tcp.

more specific, this page http://www.weatherlink.com/user/wrrc/index.php?view=main&headers=0
every 5 min update the values, so i need this info in modbus tcp to send at PLC.

the Fielbus gateway is a option fo this?

Thanks.


#2

Sure; the agent can read and parse that webpage (though obviously it’d be nice if there was a plain JSON source of it), and then send the parsed data down to the fieldbus gateway which can then send the info to a PLC over modbus TCP - libraries are available for this support.


#3

HI ingbarajas,

You could instead look at the https://openweathermap.org/api as it got a free tier and can supply the data in JSON which will be much easier to use than trying to scraping the web page which if someone changed it you will have to update your code. Your agent would poll the weather API as Hugo said and then just send the required parsed data to the device.

James


#4

I assume you specifically need the data from your University of Arizona weather station.
There doesn’t seem to be much current data, but maybe you’re working on the hardware?

You can make your own API using PHP, but you need a website to handle the PHP.

No matter what accesses the HTML, this would be a much easier URL to “scrape”:
http://www.weatherlink.com/user/wrrc/index.php?view=summary&headers=1

Every line that contains data has this string in common: "summary_data"
The number of them, the order of them, and the structure appears to remain constant.
So, if you read all of those lines into an array, you could always pick out the correct
line for each thing you need to know.

If you are using the Imp at a university, you have to be sure you can use the Imp
on their WiFi. It cannot be a “captive” WiFi system. You will need to have an SSID
and password, like a WiFi system in your home.

Out of curiosity, what kind of PLC, and PLC model number?


#5

Thanks! I will start this project


#6

Thanks james, but I have the Davis device installed in a remote location, and I need that information in detail.
Gsm gsm data is uploaded to the cloud, but I need to download it to plc level.


#7

Thanks mlseim!
I just bought a domain, and I have a server and everything I need.
I’ve never created an api, but it’s a good time to start,

I also reviewed the URL you mentioned, I also think it is easier to work on it.

The imp device will be in a production plant where we want to make historical changes in temperatures, humidity and rain, very far from the Davis weather station.

The PLC may be an allen bradley, Siemes or Invensys FoxBoro.
All these with modbus tcp / ip.


#8

Maybe a bit late, but you should seriously consider “serverless computing” when developing an API. Then if you are considering developing an App and a web-browser interface, I would recommend Google’s Firebase real-time architecture as very easy to use. You can also readily get a cloud server to point to your domain etc. (look at cloudflare) and you can also get https as standard.

Amazon AWS and IBM Bluemix also offer highly configurable enterprise grade cloud platforms.

As you are starting to learn API’s this is a good time to start and there are plenty of helpful tutorials online etc.

The best part is that Electric Imp have libraries that can readily work with any of the above cloud based platforms. Well actually the best part is that all these options offer a free tier to use too. So no monthly cost to start and you generally only pay for what you use.

Just to note that AWS and Firebase use Nodejs, JAVA or Python for their “functions” cloud system - functions is a new thing which allows you to upload back end scripts to do specific tasks when requested via http rest calls etc. AWS and IBM also allow you to use PHP too (but you would need to configure this yourself - although I no longer consider this necessary as alternatives provide all you need for a lot less work) if that is your choosing.


#9

I would say that you don’t need an Imp. You already have a URL for the Davis weather station, where your data is showing. If that data is acceptable for your plant, you can use any microcontroller that has access to the internet to read that data. I’m not sure of the deal with the weather station being “far away”. Why doesn’t the production plant have it’s own weather station? It’s not too expensive to put something on the roof of the plant. You would not need the Imp or any cloud … the hardware would be to the PLC.

Like this Davis station … on the roof of the plant and wired directly to a PLC:


#10

Hi mlseim, I have already checked those devices before, and they would have been the best option, but the control room where the plc is located is many kilometers away from the meteorological station. This is on top of hill, energized with solar cells, and the only way I have to access the information is through the http link.

The example link is from the University of Arizona, but it is not the one of my application is the same device and information.

What I need to look for are examples of how to do a scrapping of the web in the IDE agent imp, and with the libraries of modbus by electric imp, send to plc.


#11

Hello community!
I am about to finish this project but with some details even

In the agent by using 3 thingspeak API I could read 3 web pages the desired information.

Then, using three
Local request = http.get (T1500Fca_temp) and a
Device.send ("FCA", responseTable.body)
In each of them I have sent the agent information to the device.

In the device I have used 3
Agent.on ("FCA", FCA);
And a function
Function FCA (res) {
Server.log (“T1500Fca” + res); }

And I can see the log the desired value.
this a resume of all…

Now, I want to send that value through modbus, I have implemented the modbus examples of electric imp and they work by sending constant values, but when I put the variables I only send “1”

Modbus.readWriteMultipleRegisters (0, 3, 0, 3, [B13, FCA, T1545G], function (error, result)
            If (error) { Server.error (error);
            } Else {
                Foreach (index, value in result) {
                    Server.log (format ("Index:% d, value:% d", index, value));


Changing [B13, FCA, T1545G] by [45, 35, 33] for test sends these values ​​by modbus.


Now everything is focused on being able to send the variables, [B13, FCA, T1545G]
some suggestions?


#12

I suspect your problem may be the type of these variables. Please add this code and post the results:

server.log("B13="+B13+" type="+typeof B13);
server.log("FCA="+FCA+" type="+typeof FCA);
server.log("T1545G="+T1545G+" type="+typeof T1545G);

#13

2017-07-24 14:48:00 -07:00 [Device] T1500Fca 25
2017-07-24 14:48:00 -07:00 [Device] FCA=(function : 0x53c4e8) type=function
2017-07-24 14:48:00 -07:00 [Device] T1545G 25
2017-07-24 14:48:00 -07:00 [Device] T1545G=(function : 0x53eee8) type=function
2017-07-24 14:48:00 -07:00 [Device] BOMBEO13 28
2017-07-24 14:48:00 -07:00 [Device] B13=(function : 0x53c498) type=function
2017-07-24 14:48:15 -07:00 [Device] Connection timeout


#14

Sorry, that wasn’t the best instruction to give you; looking further up in your thread I see that you named your functions with the same name as the variables…

Ok, so ideally fetch all 3 from thingspeak, and send them in one single message, like this:

local request = http.get (T1500Fca_temp); 
(...)

// create blank table to send to device
local todevice = {};
todevice.FCA <- FCAresponseTable.body.tointeger();
todevice.B13 <- B13responseTable.body.tointeger();
todevice.T1545G <- T1545GresponseTable.body.tointeger();

// Send entire table to imp
device.send ("update", todevice);

Then, on the device:

agent.on("update", function(data) {
    Modbus.readWriteMultipleRegisters (0, 3, 0, 3, [data.B13, data.FCA, data.T1545G], function (error, result)
        If (error) { Server.error (error);
        } Else {
            Foreach (index, value in result) {
                Server.log (format ("Index:% d, value:% d", index, value));
(...)

#15

Hi,
i can´t send in one single message the variables, only can convert to integer and send each to device,
but cant send by modbus, is the same case before, only “1”

in this line
modbus.readWriteMultipleRegisters(0, 3, 0, 3, [B13, FCA, T1545G], function(error, result)

i try change [B13, FCA, T1545G] by [res.B13, res.FCA, res.T1545G] , [B13(res), FCA(res), T1545G(res)] and many other combinatios, but without results.
some other suggestion?

ps. check inbox…


#16

I have finally succeeded !!!:+1:

This stage of the project consists of taking 3 temperatures from websites and sending them through modbus.
As the first stage I only worked sending the temperatures
Local request = http.get (BOMBEO13_temp)

I will work later to add other information such as humidity, rain, wind, but that information comes in a single string data.
Local request = http.get (PUMP_13_data)

(I already have it in the agent)

I have added code to turn on the red led when there is some error in the modbus functions, and turn on green led when the modbus reading is done correctly.

Thanks everyone for the brainstorming!
I share the code, I hope it helps someone !!!

AGENT

    local BOMBEO13_temp = "https://api........";
    local BOMBEO13_datos = "https://api........";
    
   local T1500Fca_temp =  "https://api........";
    local T1500Fca_datos =  "https://api........";
    
    local T1545G_temp =  "https://api........";
    local T1545G_datos =  "https://api........";
  
    local todevice = {};
   

function run(){
/*-------------BOMBEO13 ----------------------*/
local request = http.get(BOMBEO13_temp)
function handleResponse(responseTable) {
    // Called when the imp receives a response from the remote service
    if (responseTable.statuscode == 200) {
        //server.log("BOMBEO13 Temp" +" " +responseTable.body); 
        todevice.B13 <- responseTable.body.tointeger();
        //server.log(todevice.B13);
        device.send("BOMBEO13", todevice.B13);
        
    
        
    } else {
        // Log an error
        server.log("Error BOMBEO13: " + responseTable.statuscode);
    }
}
request.sendasync(handleResponse);

local request = http.get(BOMBEO13_datos)
function handleResponse(responseTable) {
    // Called when the imp receives a response from the remote service
    if (responseTable.statuscode == 200) {
        //server.log("BOMBEO13 Datos" +" " + responseTable.body);
       //device.send("BOMBEO13", responseTable.body);
    } else {
        // Log an error
        server.log("Error BOMBEO13: " + responseTable.statuscode);
    }
}
request.sendasync(handleResponse);

/*-------------T1500Fca ----------------------*/
local request = http.get(T1500Fca_temp)
function handleResponse(responseTable) {
    // Called when the imp receives a response from the remote service
    if (responseTable.statuscode == 200) {
       // server.log("T1500Fca Temp" +" " + responseTable.body);
        todevice.FCA <- responseTable.body.tointeger();
        device.send("FCA", todevice.FCA);
    } else {
        // Log an error
        server.log("Error T1500Fca: " + responseTable.statuscode);
    }
}
request.sendasync(handleResponse);

local request = http.get(T1500Fca_datos)
function handleResponse(responseTable) {
    // Called when the imp receives a response from the remote service
    if (responseTable.statuscode == 200) {
       // server.log("T1500Fca Datos" +" " + responseTable.body);
      // device.send("FCA", responseTable.body);
    } else {
        // Log an error
        server.log("Error response: " + responseTable.statuscode);
    }
}
request.sendasync(handleResponse);

/*-------------T1545G ----------------------*/
local request = http.get(T1545G_temp)
function handleResponse(responseTable) {
    // Called when the imp receives a response from the remote service
    if (responseTable.statuscode == 200) {
        //server.log("T1545G Temp" +" " + responseTable.body);
        todevice.T1545G <- responseTable.body.tointeger();
        device.send("5G",  todevice.T1545G);
    } else {
        // Log an error
        server.log("Error T1545G: " + responseTable.statuscode);
    }
}
request.sendasync(handleResponse);

local request = http.get(T1545G_datos)
function handleResponse(responseTable) {
    // Called when the imp receives a response from the remote service
    if (responseTable.statuscode == 200) {
      //  server.log("T1545G Datos" +" " + responseTable.body);
     //  device.send("5G", responseTable.body)
    } else {
        // Log an error
        server.log("Error response: " + responseTable.statuscode);
    }
}
request.sendasync(handleResponse);

    imp.wakeup(240, run)
}

run();

DEVICE

#require "CRC16.class.nut:1.0.0"
#require "ModbusSlave.class.nut:1.0.0"
#require "Modbus485Slave.class.nut:1.0.0"
red <- hardware.pinP;
yellow <- hardware.pinQ;
green <- hardware.pinT;
local BOMBEO13;
local FRANCISCA;
local ULTIMA;

 
red.configure(DIGITAL_OUT, 1);
yellow.configure(DIGITAL_OUT, 1);
green.configure(DIGITAL_OUT, 1);
red.write(0)
green.write(1);

modbus <- Modbus485Slave(hardware.uart2, hardware.pinL, 1, { debug = false });
modbus.setSlaveID(1);
function B13(res) {
 //server.log("BOMBEO13 " + res);
 
 server.log("B13="+res+" type="+typeof res);
 BOMBEO13= res;
 
 }
function FCA(res) {
  server.log("T1500Fca " + res);
  FRANCISCA = res;
  
  
}
function T1545G(res) {
  server.log("T1545G " + res);
  ULTIMA = res;
}

agent.on("BOMBEO13", B13);
agent.on("FCA", FCA); 
agent.on("5G", T1545G);

modbus.onRead(function(slaveID, functionCode, startingAddress, quantity) {
    red.write(1);
    green.write(0);
return [BOMBEO13, FRANCISCA, ULTIMA,]}.bindenv(this));

modbus.onError(function(error){
    //server.error(error);
    green.write(1);
    red.write(0)
}.bindenv(this));

FIN


Modbus485Slave Adress
#17

Out of curiousity what API service did you end up going with in the end?


#18

Hi James,
i use https://thingspeak.com/apps
ThingHTTP App and use Parse String to get my data in string format, then in the agent conver to integer and send to device and rs485.

here some examples of this App
https://www.mathworks.com/help/thingspeak/thinghttp-app.html