-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from thingio/dev-yobol
first commit
- Loading branch information
Showing
35 changed files
with
2,740 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Binaries for programs and plugins | ||
*.exe | ||
*.exe~ | ||
*.dll | ||
*.so | ||
*.dylib | ||
|
||
# Test binary, built with `go test -c` | ||
*.test | ||
|
||
# Output of the go coverage tool, specifically when used with LiteIDE | ||
*.out | ||
|
||
# Dependency directories (remove the comment below to include it) | ||
# vendor/ | ||
|
||
# Dependency | ||
go.sum | ||
|
||
# IDEA | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
# edge-device-std | ||
# edge-device-std | ||
|
||
## 文档 | ||
|
||
移步[中文文档](./docs/zh)。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package config | ||
|
||
type CommonOptions struct { | ||
DriverHealthCheckIntervalSecond int `json:"driver_health_check_interval_second" yaml:"driver_health_check_interval_second"` | ||
DeviceHealthCheckIntervalSecond int `json:"device_health_check_interval_second" yaml:"device_health_check_interval_second"` | ||
DeviceAutoReconnect bool `json:"device_auto_reconnect" yaml:"device_auto_reconnect"` | ||
DeviceAutoReconnectIntervalSecond int `json:"device_auto_reconnect_interval_second" yaml:"device_auto_reconnect_interval_second"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package config | ||
|
||
import ( | ||
"flag" | ||
"github.com/mitchellh/mapstructure" | ||
"github.com/spf13/viper" | ||
"github.com/thingio/edge-device-std/errors" | ||
) | ||
|
||
const ( | ||
EnvPrefix = "eds" | ||
FilePath = "etc" | ||
FileName = "config" | ||
FileFormat = "yaml" | ||
) | ||
|
||
type Configuration struct { | ||
CommonOptions CommonOptions `json:"common" yaml:"common"` | ||
MessageBus MessageBusOptions `json:"msgbus" yaml:"msgbus"` | ||
} | ||
|
||
func NewConfiguration() (*Configuration, errors.EdgeError) { | ||
// read the configuration file path | ||
var configPath string | ||
flag.StringVar(&configPath, "cp", FilePath, "config file path, e.g. \"/etc\"") | ||
var configName string | ||
flag.StringVar(&configName, "cn", FileName, "config file name, e.g. \"config\", excluding the suffix") | ||
flag.Parse() | ||
|
||
viper.SetEnvPrefix(EnvPrefix) | ||
viper.AutomaticEnv() | ||
viper.AddConfigPath(configPath) | ||
viper.SetConfigName(configName) | ||
viper.SetConfigType(FileFormat) | ||
if err := viper.ReadInConfig(); err != nil { | ||
return nil, errors.Configuration.Cause(err, "fail to read the configuration file") | ||
} | ||
|
||
cfg := new(Configuration) | ||
if err := viper.Unmarshal(cfg, func(dc *mapstructure.DecoderConfig) { | ||
dc.TagName = FileFormat | ||
}); err != nil { | ||
return nil, errors.Configuration.Cause(err, "fail to unmarshal the configuration file") | ||
} | ||
|
||
return cfg, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package config | ||
|
||
import ( | ||
"crypto/tls" | ||
"crypto/x509" | ||
"fmt" | ||
"io/ioutil" | ||
) | ||
|
||
type ( | ||
MessageBusType = string | ||
MessageBusProtocolType = string | ||
) | ||
|
||
const ( | ||
MessageBusTypeMQTT MessageBusType = "MQTT" | ||
|
||
MessageBusProtocolTypeTCP MessageBusProtocolType = "tcp" | ||
MessageBusProtocolTypeSSL MessageBusProtocolType = "ssl" | ||
) | ||
|
||
type MessageBusOptions struct { | ||
Type MessageBusType `json:"type" yaml:"type"` | ||
MQTT MQTTMessageBusOptions `json:"mqtt" yaml:"mqtt"` | ||
} | ||
|
||
type MQTTMessageBusOptions struct { | ||
// Host is the hostname or IP address of the MQTT broker. | ||
Host string `json:"host" yaml:"host"` | ||
// Port is the port of the MQTT broker. | ||
Port int `json:"port" yaml:"port"` | ||
// Username is the username of the MQTT broker. | ||
Username string `json:"username" yaml:"username"` | ||
// Password is the password of the MQTT broker. | ||
Password string `json:"password" yaml:"password"` | ||
|
||
// ConnectTimoutMillisecond indicates the timeout of connecting to the MQTT broker. | ||
ConnectTimoutMillisecond int `json:"connect_timout_millisecond" yaml:"connect_timout_millisecond"` | ||
// TokenTimeoutMillisecond indicates the timeout of mqtt token. | ||
TokenTimeoutMillisecond int `json:"token_timeout_millisecond" yaml:"token_timeout_millisecond"` | ||
// QoS is the abbreviation of MQTT Quality of Service. | ||
QoS int `json:"qos" yaml:"qos"` | ||
// CleanSession indicates whether retain messages after reconnecting for QoS1 and QoS2. | ||
CleanSession bool `json:"clean_session" yaml:"clean_session"` | ||
|
||
// MethodCallTimeoutMillisecond indicates the timeout of method call. | ||
MethodCallTimeoutMillisecond int `json:"method_call_timeout_millisecond" yaml:"method_call_timeout_millisecond"` | ||
|
||
WithTLS bool `json:"with_tls" yaml:"with_tls"` | ||
CAPath string `json:"ca_path" yaml:"ca_path"` | ||
CertPath string `json:"cert_path" yaml:"cert_path"` | ||
KeyPath string `json:"key_path" yaml:"key_path"` | ||
} | ||
|
||
func (o *MQTTMessageBusOptions) NewTLSConfig() (*tls.Config, error) { | ||
cert, rootPool, err := o.loadTLSConfig() | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &tls.Config{ | ||
Certificates: []tls.Certificate{cert}, | ||
RootCAs: rootPool, | ||
InsecureSkipVerify: true, | ||
MinVersion: tls.VersionTLS12, | ||
}, nil | ||
} | ||
|
||
func (o *MQTTMessageBusOptions) loadTLSConfig() (tls.Certificate, *x509.CertPool, error) { | ||
cert, err := tls.LoadX509KeyPair(o.CertPath, o.KeyPath) | ||
if err != nil { | ||
return cert, nil, fmt.Errorf("fail to load the certificate files: %s", err.Error()) | ||
} | ||
rootPool := x509.NewCertPool() | ||
caCert, err := ioutil.ReadFile(o.CAPath) | ||
if err != nil { | ||
return cert, nil, fmt.Errorf("fail to load the root ca file: %s", err.Error()) | ||
} | ||
ok := rootPool.AppendCertsFromPEM(caCert) | ||
if !ok { | ||
return cert, nil, fmt.Errorf("fail to parse the root ca file") | ||
} | ||
return cert, rootPool, nil | ||
} | ||
|
||
func (o *MQTTMessageBusOptions) GetBroker() string { | ||
var protocolType MessageBusProtocolType | ||
if o.WithTLS { | ||
protocolType = MessageBusProtocolTypeSSL | ||
} else { | ||
protocolType = MessageBusProtocolTypeTCP | ||
} | ||
return fmt.Sprintf("%s://%s:%d", protocolType, o.Host, o.Port) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# CHANGELOG | ||
|
||
## 2021.12 | ||
|
||
1. 确定[系统基本架构](./系统架构/README.md) | ||
2. [设备驱动示例(生成随机数)](https://github.com/thingio/edge-randnum-driver) | ||
3. 新增特性: | ||
- 支持 command-line flag 指定配置文件路径,如 `xxx -cp etc -cn config` 表示指定配置文件为 `./etc/config.yaml` | ||
- 定义 MessageBus 接口封装 MQ 操作逻辑,并提供了 MQTTMessageBus 作为默认支持 | ||
- 定义 MetaStore 接口封装元数据操作逻辑,并提供了 FileMetaStore 作为默认支持 | ||
- 区分单向和双向操作,对于双向操作(基于 MessageBus 的 Call 方法实现)而言,使用全局唯一的 UUID - `ReqID` 标识同一组操作 | ||
- 区分属性软读(soft-read)和硬读(hard-read),前者会从设备影子(DeviceTwin)中获取该属性的缓存值,后者会直接从真实设备中读取该属性的值 | ||
- 支持 MQTTS 配置,可参考 [MQTT 使用 TLS 建立安全连接](./系统安全/MQTTS:%20MQTT%20使用%20TLS%20建立安全连接.md) | ||
- 将设备数据封装为类似于 DeviceData 的结构体,包含属性名、数据类型、数据值、数据采集时间戳等信息 | ||
|
||
## TODO | ||
|
||
1. 支持设备级别的 MQTT(S) QoS 配置 | ||
2. 为 `edge-device-manager` & `edge-device-accessor` 提供 HTTP(S) & WS(S) 访问接口及 Client,与业务无关的代码封装在 `edge-device-std` | ||
中提供基础服务 | ||
3. `edge-device-accessor` 确定业务边界、架构设计与代码实现 | ||
4. 调整 Protocol、Product 与 Device 元数据结构的定义,如 DeviceStatus 是动态消息,只能由系统更改,不应该放在 Device 这样的元数据中 | ||
5. 调研 TCP & MQTT(mosquitto) 如何切分数据包,主要是要确定当传输一个大数据文件(如图片)时,MQTT 如何将其拆分,TCP 如何将其拆分? |
Oops, something went wrong.