文章目录
海萤物联网ntp服务上线
本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
欢迎前往社区交流:海萤物联网社区
开源
介绍
基于Golang编写,在海萤物联网提供校时服务。
本机地址是:
0x2141000000000404
服务
服务号 | 服务 |
---|---|
1 | 读取时间1 |
2 | 读取时间2.返回的是结构体 |
读取时间服务1
- CON请求:空或者带符号的1个字节。
当CON请求为空时,则默认为读取的是北京时间(时区8)。
也可以带1个字节表示时区号。这个字节是有符号的int8。
小技巧,可以使用0x100减去正值即负值。比如8对应的无符号数是0x100-8=248。
- ACK应答:当前时间的字符串
当前时间字符串的格式:2006-01-02 15:04:05 -0700 MST
读取时间服务2.返回的是结构体
-
CON请求:格式与读取时间服务1一致
-
ACK应答:
struct {
// 时区
uint8 TimeZone
uint16 Year
uint8 Month
uint8 Day
uint8 Hour
uint8 Minute
uint8 Second
// 星期
uint8 Weekday
}
自定义错误码
错误码 | 含义 |
---|---|
0x40 | 内部错误 |
0x41 | 接收格式错误 |
示例
读取时间
resp, err := tziot.Call(pipe, 0x2141000000000004, 1, 1000, []uint8{})
fmt.Println("err:", err, "time:", string(resp))
输出:
err: 0 time: 2021-03-20 06:34:18 +0800 CST
读取时区为2的时间
resp, err := tziot.Call(pipe, 0x2141000000000004, 1, 1000, []uint8{2})
fmt.Println("err:", err, "time:", string(resp))
输出:
err: 0 time: 2021-03-20 00:36:31 +0200 CST
读取时区为-6的时间
resp, err := tziot.Call(pipe, 0x2141000000000004, 1, 1000, []uint8{0x100-6})
fmt.Println("err:", err, "time:", string(resp))
输出:
err: 0 time: 2021-03-19 16:36:06 -0600 CST
读取结构体格式时间
resp, _ := tziot.Call(pipe, 0x2141000000000004, 2, 3000, []uint8{8})
var ack AckRidGetTime2
_ = dcom.BytesToStruct(resp, &ack)
fmt.Println(ack)
输出:
{8 2021 3 30 12 11 28 2}
源码
最新源码请查看仓库。
main.go
// Copyright 2021-2021 The jdh99 Authors. All rights reserved.
// 网络校时服务
// Authors: jdh99 <jdh821@163.com>
package main
import (
"github.com/jdhxyy/dcom"
"github.com/jdhxyy/lagan"
"github.com/jdhxyy/tziot"
"ntp/config"
"time"
)
const tag = "ntp"
// 应用错误码
const (
// 内部错误
errorCodeInternalError = 0x40
// 接收格式错误
errorCodeRxFormat = 0x41
)
// rid号
const (
// 读取时间.返回的是字符串
ridGetTime1 = 1
// 读取时间.返回的是结构体
ridGetTime2 = 2
)
// ACK格式
type AckRidGetTime2 struct {
// 时区
TimeZone uint8
Year uint16
Month uint8
Day uint8
Hour uint8
Minute uint8
Second uint8
// 星期
Weekday uint8
}
func main() {
err := lagan.Load(0)
if err != nil {
panic(err)
}
lagan.EnableColor(true)
lagan.SetFilterLevel(lagan.LevelInfo)
_, err = tziot.BindPipeNet(config.LocalIA, config.LocalPwd, config.LocalIP, config.LocalPort)
if err != nil {
panic(err)
return
}
tziot.Register(ridGetTime1, ntpService1)
tziot.Register(ridGetTime2, ntpService2)
select {}
}
// ntpService1 校时服务
// 返回值是应答和错误码.错误码为0表示回调成功,否则是错误码
func ntpService1(pipe uint64, srcIA uint64, req []uint8) ([]uint8, int) {
addr := dcom.PipeToAddr(pipe)
var timeZone int
if len(req) == 0 {
timeZone = 8
} else if len(req) == 1 {
timeZone = int(int8(req[0]))
} else {
lagan.Warn(tag, "addr:%v ia:0x%x ntp failed.len is wrong:%d", addr, srcIA, len(req))
return nil, errorCodeRxFormat
}
t := getTime(timeZone)
lagan.Info(tag, "addr:%v ia:0x%x ntp time:%v", addr, srcIA, t)
return []uint8(t.Format("2006-01-02 15:04:05 -0700 MST")), 0
}
func getTime(timeZone int) time.Time {
t := time.Now().UTC()
secondsEastOfUTC := int((time.Duration(timeZone) * time.Hour).Seconds())
loc := time.FixedZone("CST", secondsEastOfUTC)
t = t.In(loc)
return t
}
// ntpService2 校时服务
// 返回值是应答和错误码.错误码为0表示回调成功,否则是错误码
func ntpService2(pipe uint64, srcIA uint64, req []uint8) ([]uint8, int) {
addr := dcom.PipeToAddr(pipe)
var timeZone int
if len(req) == 0 {
timeZone = 8
} else if len(req) == 1 {
timeZone = int(int8(req[0]))
} else {
lagan.Warn(tag, "addr:%v ia:0x%x ntp failed.len is wrong:%d", addr, srcIA, len(req))
return nil, errorCodeRxFormat
}
t := getTime(timeZone)
lagan.Info(tag, "addr:%v ia:0x%x ntp time:%v", addr, srcIA, t)
var ack AckRidGetTime2
ack.TimeZone = uint8(timeZone)
ack.Year = uint16(t.Year())
ack.Month = uint8(t.Month())
ack.Day = uint8(t.Day())
ack.Hour = uint8(t.Hour())
ack.Minute = uint8(t.Minute())
ack.Second = uint8(t.Second())
ack.Weekday = uint8(t.Weekday())
data, err := dcom.StructToBytes(ack)
if err != nil {
lagan.Error(tag, "addr:%v ia:0x%x ntp failed.struct to bytes error:%v", addr, srcIA, err)
return nil, errorCodeInternalError
}
return data, 0
}
config.go
// Copyright 2021-2021 The jdh99 Authors. All rights reserved.
// 配置文件
// Authors: jdh99 <jdh821@163.com>
package config
import "fmt"
// 系统参数
const (
LocalIA = 0x2141000000000004
LocalIP = "0.0.0.0"
LocalPort = 12930
)
var LocalPwd string
func init() {
fmt.Println("please input password:")
_, err := fmt.Scanln(&LocalPwd)
if err != nil {
panic(err)
}
}