A LWM2M Client and Server implementation (For Go/Golang)

Related tags

Network betwixt
Overview

Betwixt - A LWM2M Client and Server in Go

GoDoc Build Status Coverage Status Go Report Card

Betwixt is a Lightweight M2M implementation written in Go

OMA Lightweight M2M is a protocol from the Open Mobile Alliance for M2M or IoT device management. Lightweight M2M enabler defines the application layer communication protocol between a LWM2M Server and a LWM2M Client, which is located in a LWM2M Device.

The OMA Lightweight M2M enabler includes device management and service enablement for LWM2M Devices. The target LWM2M Devices for this enabler are mainly resource constrained devices. Therefore, this enabler makes use of a light and compact protocol as well as an efficient resource data model. It provides a choice for the M2M Service Provider to deploy a M2M system to provide service to the M2M User.

Basic Client Example

package main

import (
	"github.com/zubairhamed/betwixt"
	"github.com/zubairhamed/betwixt/examples"
	"github.com/zubairhamed/betwixt/examples/objects"
)

func main() {
	cli := examples.StandardCommandLineFlags()

	registry := betwixt.NewDefaultObjectRegistry()
	c := betwixt.NewLwm2mClient("TestClient", ":0", cli.Server, registry)

	setupResources(c, registry)

	c.OnStartup(func() {
		c.Register(cli.Name)
	})

	c.Start()
}

func setupResources(client betwixt.LWM2MClient, reg betwixt.Registry) {
	client.SetEnabler(betwixt.OMA_OBJECT_LWM2M_SECURITY, objects.NewExampleSecurityObject(reg))
	client.AddObjectInstances(betwixt.OMA_OBJECT_LWM2M_SECURITY, 0, 1, 2)

	client.SetEnabler(betwixt.OMA_OBJECT_LWM2M_SERVER, objects.NewExampleServerObject(reg))
	client.AddObjectInstance(betwixt.OMA_OBJECT_LWM2M_SERVER, 1)

	client.SetEnabler(betwixt.OMA_OBJECT_LWM2M_DEVICE, objects.NewExampleDeviceObject(reg))
	client.AddObjectInstance(betwixt.OMA_OBJECT_LWM2M_DEVICE, 0)

	client.EnableObject(betwixt.OMA_OBJECT_LWM2M_ACCESS_CONTROL, objects.NewExampleAccessControlObject(reg))
	client.AddObjectInstances(betwixt.OMA_OBJECT_LWM2M_ACCESS_CONTROL, 0, 1, 2)

	client.EnableObject(betwixt.OMA_OBJECT_LWM2M_CONNECTIVITY_MONITORING, objects.NewExampleConnectivityMonitoringObject(reg))
	client.AddObjectInstance(betwixt.OMA_OBJECT_LWM2M_CONNECTIVITY_MONITORING, 0)

	client.EnableObject(betwixt.OMA_OBJECT_LWM2M_FIRMWARE_UPDATE, objects.NewExampleFirmwareUpdateObject(reg))
	client.AddObjectInstance(betwixt.OMA_OBJECT_LWM2M_FIRMWARE_UPDATE, 0)

	client.EnableObject(betwixt.OMA_OBJECT_LWM2M_LOCATION, objects.NewExampleLocationObject(reg))
	client.EnableObject(betwixt.OMA_OBJECT_LWM2M_CONNECTIVITY_STATISTICS, objects.NewExampleConnectivityStatisticsObject(reg))
}

Implementing a LWM2M Object (LWM2M 'Device' Object)

import (
	. "github.com/zubairhamed/betwixt"
	"time"
)

type DeviceObject struct {
	Model       ObjectDefinition
	currentTime time.Time
	utcOffset   string
	timeZone    string
}

func (o *DeviceObject) OnExecute(instanceId int, resourceId int, req Lwm2mRequest) Lwm2mResponse {
	return Changed()
}

func (o *DeviceObject) OnCreate(instanceId int, resourceId int, req Lwm2mRequest) Lwm2mResponse {
	return Created()
}

func (o *DeviceObject) OnDelete(instanceId int, req Lwm2mRequest) Lwm2mResponse {
	return Deleted()
}

func (o *DeviceObject) OnRead(instanceId int, resourceId int, req Lwm2mRequest) Lwm2mResponse {
	if resourceId == -1 {
		// Read Object Instance
	} else {
		// Read Resource Instance
		var val Value

		switch resourceId {
		case 0:
			val = String("Open Mobile Alliance")
			break

		case 1:
			val = String("Lightweight M2M Client")
			break

		case 2:
			val = String("345000123")
			break

		case 3:
			val = String("1.0")
			break

		case 6:
			val = Integer(POWERSOURCE_INTERNAL, POWERSOURCE_USB)
			break

		case 7:
			val = Integer(3800, 5000)
			break

		case 8:
			val = Integer(125, 900)
			break

		case 9:
			val = Integer(100)
			break

		case 10:
			val = Integer(15)
			break

		case 11:
			val = MultipleIntegers(Integer(0))
			break

		case 13:
			val = Time(o.currentTime)
			break

		case 14:
			val = String(o.utcOffset)
			break

		case 15:
			val = String(o.timeZone)
			break

		case 16:
			val = String(string(BINDINGMODE_UDP))
			break

		default:
			break
		}
		return Content(val)
	}
	return NotFound()
}

func (o *DeviceObject) OnWrite(instanceId int, resourceId int, req Lwm2mRequest) Lwm2mResponse {
	val := req.GetMessage().Payload

	switch resourceId {
	case 13:
		break

	case 14:
		o.utcOffset = val.String()
		break

	case 15:
		o.timeZone = val.String()
		break

	default:
		return NotFound()
	}
	return Changed()
}

func (o *DeviceObject) Reboot() Value {
	return Empty()
}

func (o *DeviceObject) FactoryReset() Value {
	return Empty()
}

func (o *DeviceObject) ResetErrorCode() string {
	return ""
}

func NewExampleDeviceObject(reg Registry) *DeviceObject {
	return &DeviceObject{
		Model:       reg.GetDefinition(OMA_OBJECT_LWM2M_DEVICE),
		currentTime: time.Unix(1367491215, 0),
		utcOffset:   "+02:00",
		timeZone:    "+02:00",
	}
}

Minimal LWM2M Server (See /examples/server)

package main

import (
	"github.com/zubairhamed/betwixt"
	. "github.com/zubairhamed/betwixt/examples/server"
)

func main() {
	s := NewDefaultServer("8081")

	registry := betwixt.NewDefaultObjectRegistry()

	s.UseRegistry(registry)

	s.Start()
}

Limitations

  • No dTLS support.

LWM2M - Short of it

  • Device Management Standard out of OMA

  • Lightweight and compact binary protocol based on CoAP

  • Targets as light as 8-bit MCUs

Links

A primer on LWM2M

Specifications and Technical Information

Leshan - A fairly complete Java-based LWM2M implementation

You might also like...
Golang implementation of JSON-RPC 2.0 server with generics

JSON-RPC 2.0 Golang implementation of JSON-RPC 2.0 server with generics. Go 1.18+ required Features: Batch request and responses WebSockets Usage Crea

Godaddy-domains-client-go - Godaddy domains api Client golang - Write automaticly from swagger codegen

Go API client for swagger Overview This API client was generated by the swagger-codegen project. By using the swagger-spec from a remote server, you c

A go implementation of the STUN client (RFC 3489 and RFC 5389)

go-stun go-stun is a STUN (RFC 3489, 5389) client implementation in golang (a.k.a. UDP hole punching). RFC 3489: STUN - Simple Traversal of User Datag

JPRQ Customizer is a customizer that helps to use the JPRQ server code and make it compatible with your own server with custom subdomain and domain
JPRQ Customizer is a customizer that helps to use the JPRQ server code and make it compatible with your own server with custom subdomain and domain

JPRQ Customizer is a customizer that helps to use the JPRQ server code and make it compatible with your own server with custom subdomain and domain.You can upload the generated directory to your web server and expose user localhost to public internet. You can use this to make your local machine a command center for your ethical hacking purpose ;)

Http-server - A HTTP server and can be accessed via TLS and non-TLS mode

Application server.go runs a HTTP/HTTPS server on the port 9090. It gives you 4

Simple mDNS client/server library in Golang

mdns Simple mDNS client/server library in Golang. mDNS or Multicast DNS can be used to discover services on the local network without the use of an au

Server-client project with golang.
Server-client project with golang.

server-client-project Server-client project with golang. Figure 1 - Screenshot showing that the client does not work without the server running. Figur

Client-Server tcp-based file transfer application in GoLang

Клиент-серверный файловый сервис на базе протокола TCP Клиент client.go шифрует свои файлы алгоритмом AES с режимом CBC и помещает их на сервер server

A http-relay server/client written in golang to forward requests to a service behind a nat router from web

http-relay This repo is WIP http-relay is a server/client application written in go(lang) to forward http(s) requests to an application behind a nat r

Comments
  • Install error!

    Install error!

    Hi, I got errors when installing this packge as fallow:

    github.com/zubairhamed/canopus

    could not determine kind of name for C.BIO could not determine kind of name for C.BIO_get_data could not determine kind of name for C.BIO_get_shutdown could not determine kind of name for C.BIO_go could not determine kind of name for C.BIO_go_session could not determine kind of name for C.BIO_new could not determine kind of name for C.BIO_set_data could not determine kind of name for C.BIO_set_flags could not determine kind of name for C.BIO_set_init could not determine kind of name for C.CRYPTO_free could not determine kind of name for C.CString could not determine kind of name for C.DTLSv1_2_client_method could not determine kind of name for C.DTLSv1_2_server_method could not determine kind of name for C.DTLSv1_listen could not determine kind of name for C.ERR_TXT_MALLOCED could not determine kind of name for C.ERR_TXT_STRING could not determine kind of name for C.ERR_clear_error could not determine kind of name for C.ERR_func_error_string could not determine kind of name for C.ERR_get_error could not determine kind of name for C.ERR_get_error_line_data could not determine kind of name for C.ERR_lib_error_string could not determine kind of name for C.ERR_peek_error could not determine kind of name for C.ERR_reason_error_string could not determine kind of name for C.GoString could not determine kind of name for C.SSL could not determine kind of name for C.SSL_CTX could not determine kind of name for C.SSL_CTX_new could not determine kind of name for C.SSL_CTX_set_cipher_list could not determine kind of name for C.SSL_connect could not determine kind of name for C.SSL_free could not determine kind of name for C.SSL_get_error could not determine kind of name for C.SSL_get_rbio could not determine kind of name for C.SSL_new could not determine kind of name for C.SSL_read could not determine kind of name for C.SSL_set_accept_state could not determine kind of name for C.SSL_set_bio could not determine kind of name for C.SSL_shutdown could not determine kind of name for C.SSL_write could not determine kind of name for C.char could not determine kind of name for C.get_errno could not determine kind of name for C.init_ctx could not determine kind of name for C.init_lib could not determine kind of name for C.init_server_ctx could not determine kind of name for C.init_session_bio_method could not determine kind of name for C.int could not determine kind of name for C.setGoClientId could not determine kind of name for C.setGoSessionId could not determine kind of name for C.set_cookie_option could not determine kind of name for C.set_errno could not determine kind of name for C.set_proto_1_2 could not determine kind of name for C.set_psk_callback could not determine kind of name for C.uchar could not determine kind of name for C.uint could not determine kind of name for C.ulong

    gcc errors for preamble: In file included from app/gopath/src/github.com/zubairhamed/canopus/openssl/include/openssl/err.h:21:0, from app/gopath/src/github.com/zubairhamed/canopus/dtls.go:9: app/gopath/src/github.com/zubairhamed/canopus/openssl/include/openssl/bio.h: In function 'DEPRECATEDIN_1_1_0': app/gopath/src/github.com/zubairhamed/canopus/openssl/include/openssl/bio.h:680:1: error: expected declaration specifiers before 'DEPRECATEDIN_1_1_0' DEPRECATEDIN_1_1_0(int BIO_get_port(const char *str, unsigned short *port_ptr)) ^ app/gopath/src/github.com/zubairhamed/canopus/openssl/include/openssl/bio.h:687:2: error: expected declaration specifiers before ';' token };

    My OS is Linux version 4.4.0-83-generic ([email protected]) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) ) #106-Ubuntu SMP Mon Jun 26 17:54:43 UTC 2017 and the golang is go version go1.7 linux/amd64

    Need your help,Thanks a lot.

    opened by ghost 3
  • How is this different than Leshan

    How is this different than Leshan

    Hi, Could you please clarify how is this different than Leshan? Does it provide better performance? I see it lacks few features like Lack of DTLS support but what are its main points where it stands taller than Leshan.

    Thanks, Santos

    question 
    opened by nginxsantos 2
Owner
Zubair Hamed
Code Monkey, Hardware Junkie
Zubair Hamed
Golang pow implementation client <-> server over UDP and TCP protocols

Client <-> server over UDP and TCP pow protocol Denial-of-Service-attacks are a typical situation when providing services over a network. A method for

Nikita Kryuchkov 0 Jan 13, 2022
Tailscale-client-go - A client implementation for the Tailscale HTTP API

tailscale-client-go A client implementation for the Tailscale HTTP API Example p

David Bond 0 Sep 8, 2022
An open source Pusher server implementation compatible with Pusher client libraries written in Go

Try browsing the code on Sourcegraph! IPÊ An open source Pusher server implementation compatible with Pusher client libraries written in Go. Why I wro

Hava 1 Aug 27, 2022
Envoy-eds-server - Envoy EDS server is a working Envoy Discovery Service implementation

envoy-eds-server Intro Envoy EDS server is a working Envoy Discovery Service imp

Radu Crisan 2 Apr 2, 2022
A golang library about socks5, supports all socks5 commands. That Provides server and client and easy to use. Compatible with socks4 and socks4a.

socks5 This is a Golang implementation of the Socks5 protocol library. To see in this SOCKS Protocol Version 5. This library is also compatible with S

chenhao zhang 40 Nov 22, 2022
A simple FTP protocol with client and server implemented in TypeScript and Golang

websocket-ftp A simple FTP protocol with client and server implemented in TypeScript and Golang. Example (Client) const buffer: Uint8Array = (new Text

LQR471814 0 Apr 14, 2022
Gosof - A simple and easy golang socket server/client framework

Golang Socket Framework What A simple and easy golang socket server/client framework especially convenient for handling TCP fixed-length header and va

jung hyun, ko 1 Feb 27, 2022
iceportal-api is a Golang client implementation to interact with the REST API of iceportal.de when connected to the WiFi-Network offered in German ICE Trains.

iceportal-api is a Golang client implementation to interact with the REST API of iceportal.de when connected to the WiFi-Network offered in German ICE Trains.

Fabian Siegel 42 Aug 20, 2022
Use pingser to create client and server based on ICMP Protocol to send and receive custom message content.

pingser Use pingser to create client and server based on ICMP Protocol to send and receive custom message content. examples source code: ./examples Us

zznQ 13 Nov 9, 2022