Free open source Historian - Setup
Maxim Krylov
Co-founder of Kiptr.com and
MaxTech Systems
In this part we will go through setting up our historian. In Part 1 I described the installation of Linux VM, Node-RED, InfluxDB and Grafana.
Now it's time to set up all the pieces.

Before we proceed I wanted to say that we, at MaxTech Systems, are always ready to discuss your controls engineering needs. Please contact us if you need any help with your projects. Phone, email, LinkedIn - we will answer!
We will start with setting up communications to our PLC in Node-RED. Then we will create a bucket in InfluxDB to store our data and finally we will see how to create and organize trends in Grafana.
For demonstration purposes we will save and trend the three tags:
System seconds (SINT)
System mseconds (REAL)
Minute bit (BOOL) that will change the state twice a minute
I am using another VM to program my PLC. My add on instruction is using GSV to get the time from the processor and then simply distributes it over the corresponding output variables.
I am not going deep into how to setup virtual machine and communications with PLC. There is plenty of information about it. But before continuing please make sure that your Linux VM can communicate with your PLC. For that, simply ping the PLC from the terminal. I set my Linux VM network adapter to share IP with my host (NAT option). That way I can keep IP address in auto (DHCP) mode in Linux.
Node-RED
First, open the Node-RED interface. It is available at localhost:1880 by default.
Click on the hamburger icon in the top right corner and select "Manage palette".
We will install the libraries that we need to communicate to PLCs and store information to InfluxDB.
Go to "Install" tab and search for "CIP". You will see several libraries available. I used the "node-red-contrib-cip-ethernet-ip". Others are also available but still need to be tested.
Click "Install" and follow the prompts.
Next, search for "InfluxDB" and install "node-red-contrib-influxdb"
Now let's test our communication!
Hit the Close button to exit the Palette and look at the nodes on the left side of the screen. At the very end of the list you will find "plc" section with two nodes - "eth - ip in" and "eth - ip out". These can be used to read and write information to Rockwell PLCs.
Drag and drop the "eth - ip in" to the Flow Sheet. Double click it.
Click the edit button at the end of the PLC line.
Enter the PLC address. In my case it is 10.4.129.16. Obviously yours may be totally different. Enter the slot number (leave at 0 for CompactLogix).
You can also enter the name for your PLC. If left empty, IP address (or a tag) will be used as the name.
Cycle time - enter the desired time of data refresh. This will be used mainly if you select "All tags" option (see below). For other options data is refreshed "on change" but no more often then the cycle time.
Navigate to the "Tags" tab.
Let's start with reading a simple BOOL. In my PLC it is a tag with the name"Min_bit".

Click red "Add" button in the top right corner to get to the previous screen.
Here we will select "Single Tag" mode and select our tag from the drop down list:
Click "Done".
Now, on the Flow Sheet drag and drop the "Debug" node from the Common section and connect our Ethernet IP nod with Debug node. This will output the result of our node into the debug window.
Switch to debug window (the little bug button) and lastly, press Deploy.
If everything works - you should see the result of your communication request in the debug window.
Ok, great! Communication is working. Let's go ahead and add the other tags.
Double click the Ethernet IP node and go into PLC edit window.
Click on "Tags" tab.
Import and export is important if you have more than just a few tags. If you want to save a ton of time and generate the list of tags that you need to trend - use kiptr.com functionality. It allows to process your PLC program and generate an excel spreadsheet or a csv file.
Here you will find some examples.
Feel free to contact me for additional details and demo.
All my tags are global scoped, so I will go ahead and them to the list. Once that is done - press "Update" button.
Now we have a choice - do we want to read a single tag or all of them at once.
Obviously at the end of the day we want to read all of them and store the data to the database.
But at this point I faced an unpleasant surprise when I worked on my last project.
Let's set the mode to "All tags". For now, I would recommend to also set the cycle time to something like 1 second or higher (same tab where we set the PLC IP address). Now look at what happens after you hit Deploy button.
You will mention that every 1 second (or whatever you set your cycle time to) instead of one answer you will be getting multiple answers. This happens because the Ethernet IP node is written in such a way. I will not go too deep into that here but it is not a problem when you need to update 5-10 tags. In my case of my last project I was reading hundreds of tags and I wanted them updated 10 times a second. I was quite surprised to see my processor usage at maximum and database rejecting that number of writes.
So again, if you don't need to work with large number of tags - next section is optional for you. Others - please keep reading.

Node-RED - updating the library (optional)
I tried several different approaches and decided to stop on the following:
If "All tags" option is selected I want all tags to be updated exactly every <Cycle Time>. This will not depend on if the value was changed or not - I will just write the current value to the database every <Cycle Time> milliseconds.
This is also important because Grafana does not like it when the value of a tag is missing in the current area (time window) of the query. It will show a broken line. Yes, there are ways around it but again, for my purposes this approach was ideal.

I am open for discussions and improvements.
So to fix the issue, I modified the original library. My modified version can be downloaded here. Modified code is between "/===" signs.
I have also sent an email to the author with explanation of the problem.
In short, how to update the library in Linux (there are several ways of course).
You can copy-paste the code directly (open file in any text editor) or replace the file.
Here is how to replace the file:
Create a shared folder with the VM. If you are using latest version of VMWare chances are that you don't need to install VMWare Tools. You can navigate to
Files --> Other Locations --> Computer/mnt/hgfs
In that folder you should see the contents of the shared folder on the host (disable and enable sharing again if nothing is in there).
Drop the modified library in the shared folder on the host and you can copy-paste it inside Linux.

Node-RED nodes are located in ~/.node-red/
To get to this folder, go to
Files --> Home --> press Control+L --> add .node-red/ and press Enter

Once in the folder, navigate to
node_modules/node-red-contrib-cip-ethernet-ip/red/
Rename the old ethernet-ip.js.
Paste the modified file.
Restart Node-RED service or simply reboot VM.
Now your scan should give you a nice single answer every time the request is sent. You can set the cycle time to whatever your network and computer resources allow.
End of optional section, back to Node-RED
If we look at what we are getting back from the Ethernet IP node than we will see something like the following:

{
    "Min_bit": true,
    "PLC_TIME.SEC": 53,
    "PLC_TIME.MSEC_REAL": 674.6240234375
}

What it is - is a simple Java object aka JSON. We need to feed it to the database.
What database is expecting - an array of JS objects in the following format:


{
    "measurement": "Tag_value",
    "fields": {
        "value": xxx
    }
}
I am simplifying it here, in fact you can play with the object and create various scenarios. But the option above is the simplest way to achieve what we need.
So what we need to do - convert one JSON to the array of JSONs. To do that, I wrote a simple script. It can be implemented using a Function node.
Under functions, locate "Function" node, drag and drop it to the Sheet and connect to the Ethernet-IP node. Debug will be connected to the output of Function node like that:

Now double click the Function node and paste the following script:

var tagnames = Object.keys(msg.payload);
let allTags = msg.payload;
msg.payload = [];
tagnames.forEach((tagname) => {
    let newTag = {};
    newTag.measurement = tagname;
    let fields = {};
    if (allTags[tagname] == true) fields.value = 1;
    else if (allTags[tagname] == false) fields.value = 0;
    else fields.value = allTags[tagname];
    newTag.fields = fields;
    msg.payload.push(newTag);
});
msg.topic = "PLC_Name";
return msg;
What we do here is rearrange the data in the form acceptable by database and also we convert "true" and "false" responses to "1" and "0" so that we could trend boolean data.
And now here is what we have on our output:

[{
    "measurement": "Min_bit",
    "fields": {
        "value": 0
    }
}, {
    "measurement": "PLC_TIME.SEC",
    "fields": {
        "value": 6
    }
}, {
    "measurement": "PLC_TIME.MSEC_REAL",
    "fields": {
        "value": 825.2969970703125
    }
}]
InfluxDB
Time to get prepared to store our data to database. This will probably be the easiest portion of the whole project.
Go to localhost:8086 and you should find the welcome screen of InfluxDB.
Enter the required information and hit Continue
On the next screen you can select Quick Start.
Next, click on "Load Data" icon and select "Buckets". By default the pane is collapsed, you can extend it pressing a little icon in the lower left corner of the screen. That way you will see the menu with descriptions, not only icons.
Create new bucket, give it a name and select if you want to keep the data forever or discard it after some time.
Next, go to API tokens and add a new token. You can choose what permissions will that token have. In this example I am generating the global token with full access.
Once token is generated, copy it and save for yourself. You will not be able to get this token again. But you can always delete this one and generate another one. Tokens are used to get access to the database.
In this example you will need it twice - once for Node-RED and once for Grafana.
Now time to save the data to the bucket. Go to Node-RED, find the section "Storage" and drag and drop the "influx batch" node.
Connect it to the Function node and double click on "influx batch".
Here we need to create a new server (screenshot below) and fill out the name (whatever), Organiztion (has to match the organization you entered when creating InfluxDB account) and bucket name (has to match the existing bucket).
Time precision - up to you, I left milliseconds since I was writing 10 times a second.
Server configuration:
Name (whatever), version 2.0, url - default, Token - paste your existing token.
Update --> Done --> Deploy. If everything went well nothing should change in the debug window - you should still see the responses from PLC. If you made a mistake - you will see the error text in the debug window.
Now, go back to Buckets in InfluxDB and click the bucket that you chose to store data into:
Select your bucket --> Put checkmarks next to your tags --> checkmark "value" --> select the time frame --> hit "Submit"
You should see your data on the trend!
That means that your data safely made it to the database and now we can get to setting up Grafana for our beutiful trends!
Grafana
Grafana is available at localhost:3000
Default login/password are both set to "admin".
When you sign in for the first time, you will be asked to enter a new password.
First thing we need to do is to add a data source. Go to Settings and press the Add data source button.
Select InfluxDB.
Query Language - select Flux.
Set URL to "http://localhost:8086"
Unselect all the items in Auth section.
Add your organization, Token and default bucket.
Set Min time interval to the minimum data write time in the database.
Click Save & Test. You should see a success message.

Let's go to Dashboards. Here you can create new Folders, Dashboards or import Dashboards.
Let's create a new Dashboard.
Everything here is pretty straight forward. You can go to Settings and give this dashboard a name. After that save it.
Let's add our first panel.
Everything here is pretty straight forward. You can go to Settings and give this dashboard a name. After that save it.
Let's add our first panel.
Give it a name if you want.
Now the only thing it is missing is the query. We don't have to worry about selecting the datasource since we have only one and it is selected by default.
Good news is - we don't have to write the query - InfluxDB does it for us. As a matter of a fact you have already done it when you displayed the trend in InfluxDB. We only need to go there and copy it. So head back to InfluxDB.
Press the button Script Editor and you will see the text.
You can generate queries by simply picking the tags from the list in InfluxDB or write them in any text editor. It's pretty self-explanatory.
Here is what I got:
So after pasting it in grafana you can switch to any field (for example - Title) and you should see the trend. Change your time range if you need.
To make any trend a little prettier, it makes sense to use "Overrides" - you can change the name of the tags (the way they are displayed under the trend), change the minimum and maximum values (scaling).
I will show how to do it for individual tags.
First, go to Overrides tab and choose "Fields with name".
When adding a new field to the the override you may simply start typing what you are looking for and system will narrow down the list for you. For name you can start typing "display", for minimum and maximum - "min" and "max" etc.
When you save your trend and get back to the dashboard - select the auto refresh rate.
By default fastest is 5s. It is possible to add a faster rate, but for that you will need to go to text configuration files for Grafana.
Don't forget that you can rearrange your panels (trends) on the dashboard, change size etc. Also time-series is only one type of panel. When you go to edit the panel you can select other types in the right top corner of the window.

Pretty much that is it. Congratulations, now you are armed and dangerous!
I hope you will find this useful!

Last note - there is a ton of information available online about every piece of this great combo. Don't be shy and google anything you want to change.