/goplc

A Lightweight Ethernet/IP API written to interface with Rockwell ControlLogix/CompactLogix Controllers.

Primary LanguageGoMIT LicenseMIT

Repositorie moved to go-cip

golang version MIT license GitHub stars

goplc

A golang based API(Originator) for interfacing with Rockwell Control/CompactLogix PLCs.

NOTE: goplc running in a single go route and never block your process, you need to block it by other way.

Thanks

node-ethernet-ip project gave me a lot of inspiration.

The API

The Basics

Hello world

import (
    "github.com/MiguelValentine/goplc"
)

func test(){
    //IP Slot Config
    plc, _ := NewOriginator("1.1.1.1", 1, nil)
    plc.OnConnected = func() {
        log.Printf("%+v\n",plc.Controller)
        // &{VendorID:1 DeviceType:14 ProductCode:53 Major:32 Minor:11 Status:12400 SerialNumber:1881423856 Version:32.11 Name:Emulator R32.11}
    }
    
    _ = plc.Connect()
}

Config

import (
    "github.com/MiguelValentine/goplc"
)

func test(){
    cfg := DefaultConfig()

    //Reconnection Interval  default will not automatically reconnect
    cfg.ReconnectionInterval = time.Second

    //Logger  default no log
    cfg.Logger = log.New(os.Stdout, "", log.LstdFlags)

    //default 0xAF12
    cfg.Port = 1111

    plc, _ := NewOriginator("1.1.1.1", 1, cfg)
    plc.OnConnected = func() {
        log.Printf("%+v\n",plc.Controller)
        // &{VendorID:1 DeviceType:14 ProductCode:53 Major:32 Minor:11 Status:12400 SerialNumber:1881423856 Version:32.11 Name:Emulator R32.11}
    }
    
    _ = plc.Connect()
}
ListAllTags
import (
    "github.com/MiguelValentine/goplc"
)

func testListAllTags() {
    cfg := DefaultConfig()
    plc, _ := NewOriginator("1.1.1.1", 1, cfg)
    plc.OnConnected = func() {
        plc.ListAllTags(0)
        //  2020/08/24 17:20:10 Map:Local : (0x1069)
        //  2020/08/24 17:20:10 Task:MainTask : (0x1070)
        //  2020/08/24 17:20:10 Program:MainProgram : (0x1068)
        //  2020/08/24 17:20:10 TESTA : DINT(0xc4)
        //  2020/08/24 17:20:10 TESTB : (0xafce)
        //  2020/08/24 17:20:10 TESTC : DINT(0xc4)
        //  2020/08/24 17:20:10 TESTD : REAL(0xca)
        //  2020/08/24 17:20:10 TESTE : (0x8fce)
    }

    _ = plc.Connect()
}

ReadAndWriteTag

NOTE: Currently, the Tag Class only supports Atomic datatypes(SINT, INT, DINT, REAL, BOOL) and String Read(not support string write).support for ARRAY, and UDTs are in the plans and coming soon!

import (
    "github.com/MiguelValentine/goplc"
    "github.com/MiguelValentine/goplc/tag"
)

func testTag() {
    tagA := tag.NewTag("TESTA")

    //OnData will be called every time you sync
    //Try to use OnChange if not necessary
    tagA.OnData = func(value interface{}) {
        log.Println(value)
        //1237
        //1238
    }

    plc, _ := NewOriginator("1.1.1.1", 1, nil)
    plc.OnConnected = func() {
        log.Printf("%+v\n", plc.Controller)
        plc.ReadTag(tagA).Then(func() {
            tagA.SetValue(int32(1238))
            plc.WriteTag(tagA).Then(func() {
                plc.ReadTag(tagA)
            })
        })
    }

    _ = plc.Connect()
}

TagGroup

import (
    "github.com/MiguelValentine/goplc"
    "github.com/MiguelValentine/goplc/tag"
    "github.com/MiguelValentine/goplc/tagGroup"
)

func testTagGroup() {
    cfg := DefaultConfig()

    tagA := tag.NewTag("TESTA")
    tagA.OnChange = func(value interface{}) {
        log.Println(value)
    }
    tagB := tag.NewTag("TESTB")
    tagB.OnChange = func(value interface{}) {
        log.Println(value)
    }
    tg := &tagGroup.TagGroup{}
    tg.Add(tagA)
    tg.Add(tagB)

    plc, _ := NewOriginator("1.1.1.1", 1, cfg)
    plc.OnConnected = func() {
        plc.ReadTagGroup(tg)
    }

    _ = plc.Connect()
}

Sync

import (
    "github.com/MiguelValentine/goplc"
    "github.com/MiguelValentine/goplc/tag"
    "github.com/MiguelValentine/goplc/tagGroup"
)

func testTagGroup() {
    cfg := DefaultConfig()

    tagA := tag.NewTag("TESTA")
    tagA.OnChange = func(value interface{}) {
        log.Printf("%s => %f\n", tagA.Name(), value)
    }

    tagB := tag.NewTag("TESTB")
    tagB.OnChange = func(value interface{}) {
        log.Printf("%s => %f\n", tagB.Name(), value)
    }
    tg := &tagGroup.TagGroup{}
    tg.Add(tagA)
    tg.Add(tagB)

    plc, _ := NewOriginator("1.1.1.1", 1, cfg)
    plc.OnConnected = func() {
        //setTimeInterval
        plc.ReadTagGroupInterval(tg, time.Millisecond*50)
    }

    _ = plc.Connect()
}

License

This project is licensed under the MIT License - see the LICENCE file for details