# Simple API to read and write to Ignition tags

**URL:** <https://forum.inductiveautomation.com/t/simple-api-to-read-and-write-to-ignition-tags/2171>\
**Category:** Ignition\
**Created:** [September 3, 2010, 5:11pm UTC](https://forum.inductiveautomation.com/t/simple-api-to-read-and-write-to-ignition-tags/2171 "2010-09-03T17:11:22Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Automate](https://avatars.discourse-cdn.com/v4/letter/a/51bf81/32.png) [@Automate](https://forum.inductiveautomation.com/u/Automate)\
**Post date:** [September 3, 2010, 5:11pm UTC](https://forum.inductiveautomation.com/t/simple-api-to-read-and-write-to-ignition-tags/2171/1 "2010-09-03T17:11:22Z")

</div>

I have 3 working Python, quasi driver programs I would like to incorporate into Ignition applications. Unfortunately some of the modules required by the existing programs are not available in Ignition’s Jython 2.1 and users do not have the ability to add modules. The 3 program are as follows:

1. Application that extracts data from a remote web page (requires urllib2, re and BeautifulSoup)
2. Application that calculates local sunrise and sunset times (requires math and pytz)
3. Application that communicates with serial port devices (requires serial)

Ignition has other ways to work around this problem but each have their disadvantages.

1. Convert the programs into OPC-UA servers. This would require the purchase of a third party OPC-UA driver toolkit and a somewhat steep learning curve for using the toolkit. Not a good solution when only needing to transfer a few tag values and don’t want the complexity of OPC which is optimized for transferring large numbers of tags.
2. Rewrite the programs into an Ignition modules using the new module toolkit. I would rather not have to re-write the applications especially since I do not have experience in Java.
3. Use Ignition’s python scripting with the functionality of unavailable python modules re-written in Java. Again, requires some re-writing and knowledge of Java. Also, I doubt keeping a serial port open in a python script would work very well since Ignition scripts are not designed to run continuously.

What would be nice to have is a simple API that allows any external program written in any language that support sockets to read and write Ignition tags. A simple protocol maybe using JSON would be great. The API could also be used with external MES and ERP applications.

I realize not using the security features available to OPC-UA has some issues but the API socket could be off by default. Anyone wanting to use the feature would have to explicitly turn it on. Also, tens of thousands of current OPC-DA server are currently operating with the same risk.

---

<div class="post-metadata">

**Author:** ![Robert](https://avatars.discourse-cdn.com/v4/letter/r/e95f7d/32.png) [@Robert](https://forum.inductiveautomation.com/u/Robert)\
**Post date:** [September 3, 2010, 8:34pm UTC](https://forum.inductiveautomation.com/t/simple-api-to-read-and-write-to-ignition-tags/2171/2 "2010-09-03T20:34:58Z")

</div>

You could use DB tags.

There is a paper somewhere here that says how to setup a DB tag table that can be driven externally.  
Basically you would define the tags in a database then your Python script would update the value and lastchange columns when something changes.

---

<div class="post-metadata">

**Author:** ![Automate](https://avatars.discourse-cdn.com/v4/letter/a/51bf81/32.png) [@Automate](https://forum.inductiveautomation.com/u/Automate)\
**Post date:** [September 3, 2010, 9:10pm UTC](https://forum.inductiveautomation.com/t/simple-api-to-read-and-write-to-ignition-tags/2171/3 "2010-09-03T21:10:23Z")

</div>

Thanks, that is an option but it requires installing and maintaining a SQL database and excludes Panel Edition.

---

<div class="post-metadata">

**Author:** ![Colby.Clegg](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/colby.clegg/32/3282_2.png) [@Colby.Clegg](https://forum.inductiveautomation.com/u/Colby.Clegg)\
**Post date:** [September 4, 2010, 12:53am UTC](https://forum.inductiveautomation.com/t/simple-api-to-read-and-write-to-ignition-tags/2171/4 "2010-09-04T00:53:33Z")

</div>

I think there are more options than what you list. I’ll think about this some more this weekend, but was just about to run out the door, saw this, and wanted to reply (these points are mostly just general observations, not direct replies to your points):

- Our module SDK essentially can be OPC-UA toolkit - you can write drivers that then get exposed through our OPC-UA server.

- Someone could write a module that basic acts as a python interface to our API. That is, build a module that has a newer version of jython and lets you load other python libraries.

- Your simple JSON interface could probably be written very easily using the current SDK.

I’m most interested in the 2nd point. I’ve always thought we should do something like this… but of course, ideas are cheap around here, and it just hasn’t been very high on the list.

Anyhow, as I said, I just wanted to throw some things out there- everyone can think about it and come back on tuesday 😃

---

<div class="post-metadata">

**Author:** ![SteveE](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/stevee/32/14460_2.png) [@SteveE](https://forum.inductiveautomation.com/u/SteveE)\
**Post date:** [November 22, 2011, 1:04am UTC](https://forum.inductiveautomation.com/t/simple-api-to-read-and-write-to-ignition-tags/2171/5 "2011-11-22T01:04:02Z")

</div>

VBA Code to calculate Sunrise and Sunset times in Auckland, NZ. Will need a bit of a tweak to Parameterize and Pythonorize it but it is all proven in the field.

[code]Sub Main  
Dim vSunRiseTime As String  
Dim vSunSetTime As String  
Dim Season As String  
Dim vTime As Date

```
vTime = Now
If GetTimeZone = "New Zealand Daylight Time" Then
    Season = "Summer"
Else
    Season = "Winter"
End If
vSunRiseTime = SunRiseSet("SunRise", 4) '4 minutes past sun rise
vSunSetTime = SunRiseSet("SunSet", 30) '30 minutes past sunset

```

End Sub

Private Function SunRiseSet(vSunRiseOrSunSet As String, vMinuteOffset As Integer) As String  
Dim vTimeOffset As Double  
Dim vLatitude As Double  
Dim vLongitude As Double  
Dim vZenith As Double  
Dim vTimeZone As Integer 'Number of hours from UTC  
Dim pi As Double  
Dim vYear As Integer  
Dim vDays As Integer  
Dim lngHour As Double 'Longitudinal hour  
Dim SinDec, CosDec As Double  
Dim T As Double 'Local mean time of rising / setting  
Dim Mdeg As Double  
Dim Ldeg As Double  
Dim RA As Double  
Dim LQuadrant, RAQuadrant As Integer  
Dim COSh As Double  
Dim H As Double  
Dim UT As Double  
Dim LocalT As Double  
Dim vHour As Integer  
Dim vMinute As Integer

```
pi = 4 * Atn(1)
vLongitude = 174.766667 'Degrees: Auckland
vLatitude = -36.866667 'Degrees: Auckland
vZenith = 90.833 'Sun's zenith for sunrise/sunset
If Season = "Summer" Then
    vTimeZone = 13
Else
    vTimeZone = 12
End If

'Find the number of days so far this year
vYear = DatePart("yyyy", vTime)
vDays = DateDiff("d", DateSerial(vYear, 1, 1), vTime) + 1

'Convert longitude to hour value and calculate the approximate time
lngHour = vLongitude / (360 / 24)

'Approximate rising time in decimal days
If vSunRiseOrSunSet = "SunRise" Then T = vDays + ((6 - lngHour) / 24)

'Approximate setting time in decimal days
If vSunRiseOrSunSet = "SunSet" Then T = vDays + ((18 - lngHour) / 24)

'Calculate the Sun's mean anomaly
Mdeg = (0.9856 * T) - 3.289 'Degrees
Ldeg = Limit360(Mdeg + (1.916 * Sin(Radians(Mdeg))) + (0.02 * Sin(2 * Radians(Mdeg))) + 282.634) 'Degrees
RA = Limit360((180 / pi) * Atn(0.91764 * Tan(Radians(Ldeg))))
LQuadrant = (Floor(Ldeg / 90)) * 90
RAQuadrant = (Floor(RA / 90)) * 90
RA = RA + (LQuadrant - RAQuadrant)
RA = RA / 15
SinDec = 0.39782 * Sin(Radians(Ldeg))
CosDec = Cos(ArcSin(SinDec))
COSh = (Cos(Radians(vZenith)) - (SinDec * Sin(Radians(vLatitude)))) / (CosDec * Cos(Radians(vLatitude)))

```

’ if if rising time is desired:  
If vSunRiseOrSunSet = “SunRise” Then H = 360 - ((180 / pi) \* ArcCos(COSh))  
’ if setting time is desired:  
If vSunRiseOrSunSet = “SunSet” Then H = (180 / pi) \* ArcCos(COSh)

```
H = H / 15
T = H + RA - (0.06571 * T) - 6.622
UT = Limit24(T - lngHour)
LocalT = Limit24(UT + vTimeZone) 'Decimal hours
vHour = Floor(LocalT)
vMinute = (LocalT - vHour) * 60
'Apply offset
vMinute = vMinute + vMinuteOffset
If vMinute >= 60 Then
    vMinute = vMinute - 60
    vHour = vHour + 1
End If
SunRiseSet = Format(vHour, "00") & ":" & Format(vMinute, "00")

```

End Function

Private Function Limit24(vX As Variant) As Double  
Do  
If vX \> 24 Then vX = vX - 24  
Loop Until vX \< 24  
Do  
If vX \< 0 Then vX = vX + 24  
Loop Until vX \>= 0  
Limit24 = vX  
End Function

Private Function Limit360(vX As Variant) As Double  
Do  
If vX \> 360 Then vX = vX - 360  
Loop Until vX \< 360  
Do  
If vX \< 0 Then vX = vX + 360  
Loop Until vX \>= 0  
Limit360 = vX  
End Function

Private Function Radians(vX As Variant) As Double  
Dim pi As Double  
pi = 4 \* Atn(1)  
Radians = vX \* pi / 180  
End Function

Private Function ArcCos(vX As Variant) As Variant  
'Radians in, radians out  
'Arccos(X) = Atn(-X / Sqr(-X \* X + 1)) + 2 \* Atn(1)  
ArcCos = Atn((-1 \* vX) / Sqr(-1 \* vX \* vX + 1)) + (2 \* Atn(1))  
End Function

Private Function ArcSin(vX As Variant) As Variant  
'Arcsin(X) = Atn(X / Sqr(-X \* X + 1))  
ArcSin = Atn(vX / Sqr(-1 \* vX \* vX + 1))  
End Function

Public Function Ceiling(ByVal X As Double, Optional ByVal Factor As Double = 1) As Double  
’ X is the value you want to round  
’ is the multiple to which you want to round  
Ceiling = (Int(X / Factor) - (X / Factor - Int(X / Factor) \> 0)) \* Factor  
End Function

Public Function Floor(ByVal X As Double, Optional ByVal Factor As Double = 1) As Double  
’ X is the value you want to round  
’ is the multiple to which you want to round  
Floor = Int(X / Factor) \* Factor  
End Function

Private Type SYSTEMTIME  
wYear As Integer  
wMonth As Integer  
wDayOfWeek As Integer  
wDay As Integer  
wHour As Integer  
wMinute As Integer  
wSecond As Integer  
wMilliseconds As Integer  
End Type

Private Type TIME\_ZONE\_INFORMATION  
Bias As Long  
StandardName(0 To 31) As Integer  
StandardDate As SYSTEMTIME  
StandardBias As Long  
DaylightName(0 To 31) As Integer  
DaylightDate As SYSTEMTIME  
DaylightBias As Long  
End Type

Private Declare Function GetTimeZoneInformation Lib “kernel32.dll” (lpTimeZoneInformation As TIME\_ZONE\_INFORMATION) As Long  
Public Function GetTimeZone(Optional ByRef strTZName As String) As String  
Dim objTimeZone As TIME\_ZONE\_INFORMATION  
Dim lngResult As Long  
Dim i As Long  
lngResult = GetTimeZoneInformation&(objTimeZone)  
Select Case lngResult  
Case 0&, 1& 'use standard time  
GetTimeZone = -(objTimeZone.Bias + objTimeZone.StandardBias) 'into minutes  
For i = 0 To 31  
If objTimeZone.StandardName(i) = 0 Then Exit For  
strTZName = strTZName & Chr(objTimeZone.StandardName(i))  
Next  
Case 2& 'use daylight savings time  
GetTimeZone = -(objTimeZone.Bias + objTimeZone.DaylightBias) 'into minutes  
For i = 0 To 31  
If objTimeZone.DaylightName(i) = 0 Then Exit For  
strTZName = strTZName & Chr(objTimeZone.DaylightName(i))  
Next  
End Select  
GetTimeZone = strTZName  
End Function[/code]

---

<div class="post-metadata">

**Author:** ![Kyle\_Chase](https://avatars.discourse-cdn.com/v4/letter/k/9de0a6/32.png) [@Kyle\_Chase](https://forum.inductiveautomation.com/u/Kyle_Chase)\
**Post date:** [November 22, 2011, 4:06am UTC](https://forum.inductiveautomation.com/t/simple-api-to-read-and-write-to-ignition-tags/2171/6 "2011-11-22T04:06:25Z")

</div>

Creating a SQLTag provider using the API really is not that hard. Give it a shot and I think you will be able to figure it out.
