blob: 652889d4b0454d68fd3c221f916371edc87a1f9d [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package config
import (
log "github.com/Sirupsen/logrus"
"github.com/mitchellh/go-homedir"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
"mynewt.apache.org/newt/util"
"mynewt.apache.org/newtmgr/newtmgr/nmutil"
)
type ConnProfileMgr struct {
profiles map[string]*ConnProfile
}
type ConnType int
type ConnProfile struct {
Name string `json:"MyName"`
Type ConnType `json:"MyType"`
ConnString string `json:"MyConnString"`
}
func (p *ConnProfile) String() string {
return fmt.Sprintf("name=%s type=%s connstring=%s",
p.Name, ConnTypeToString(p.Type), p.ConnString)
}
const (
CONN_TYPE_NONE ConnType = iota
CONN_TYPE_SERIAL_PLAIN
CONN_TYPE_SERIAL_OIC
CONN_TYPE_BLL_PLAIN
CONN_TYPE_BLL_OIC
CONN_TYPE_BLE_PLAIN
CONN_TYPE_BLE_OIC
CONN_TYPE_UDP_PLAIN
CONN_TYPE_UDP_OIC
CONN_TYPE_MTECH_LORA_OIC
)
var connTypeNameMap = map[ConnType]string{
CONN_TYPE_SERIAL_PLAIN: "serial",
CONN_TYPE_SERIAL_OIC: "oic_serial",
CONN_TYPE_BLL_PLAIN: "ble",
CONN_TYPE_BLL_OIC: "oic_ble",
CONN_TYPE_BLE_PLAIN: "bhd",
CONN_TYPE_BLE_OIC: "oic_bhd",
CONN_TYPE_UDP_PLAIN: "udp",
CONN_TYPE_UDP_OIC: "oic_udp",
CONN_TYPE_MTECH_LORA_OIC: "oic_mtech",
CONN_TYPE_NONE: "???",
}
func ConnTypeToString(ct ConnType) string {
return connTypeNameMap[ct]
}
func ConnTypeFromString(s string) (ConnType, error) {
for k, v := range connTypeNameMap {
if s == v {
return k, nil
}
}
return ConnType(0), util.FmtNewtError("Invalid connection type: %s", s)
}
func (t *ConnType) MarshalJSON() ([]byte, error) {
return json.Marshal(ConnTypeToString(*t))
}
func (ct *ConnType) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
var err error
*ct, err = ConnTypeFromString(s)
if err != nil {
*ct = CONN_TYPE_NONE
}
return nil
}
func NewConnProfileMgr() (*ConnProfileMgr, error) {
cpm := &ConnProfileMgr{
profiles: map[string]*ConnProfile{},
}
if err := cpm.Init(); err != nil {
return nil, err
}
return cpm, nil
}
func connProfileCfgFilename() (string, error) {
dir, err := homedir.Dir()
if err != nil {
return "", util.NewNewtError(err.Error())
}
return filepath.Join(dir, nmutil.ToolInfo.CfgFilename), nil
}
func (cpm *ConnProfileMgr) Init() error {
filename, err := connProfileCfgFilename()
if err != nil {
return err
}
log.Debugf("Reading connection profiles from %s", filename)
blob, err := ioutil.ReadFile(filename)
if err != nil {
if os.IsNotExist(err) {
return nil
} else {
return util.ChildNewtError(err)
}
}
var profiles []*ConnProfile
if err := json.Unmarshal(blob, &profiles); err != nil {
return util.FmtNewtError("error reading connection profile "+
"config (%s): %s", filename, err.Error())
}
for _, p := range profiles {
cpm.profiles[p.Name] = p
}
return nil
}
type connProfSorter struct {
cps []*ConnProfile
}
func (s connProfSorter) Len() int {
return len(s.cps)
}
func (s connProfSorter) Swap(i, j int) {
s.cps[i], s.cps[j] = s.cps[j], s.cps[i]
}
func (s connProfSorter) Less(i, j int) bool {
return s.cps[i].Name < s.cps[j].Name
}
func SortConnProfs(cps []*ConnProfile) []*ConnProfile {
sorter := connProfSorter{
cps: make([]*ConnProfile, 0, len(cps)),
}
for _, p := range cps {
sorter.cps = append(sorter.cps, p)
}
sort.Sort(sorter)
return sorter.cps
}
func (cpm *ConnProfileMgr) GetConnProfileList() ([]*ConnProfile, error) {
log.Debugf("Getting list of connection profiles")
cpList := make([]*ConnProfile, 0, len(cpm.profiles))
for _, p := range cpm.profiles {
cpList = append(cpList, p)
}
return SortConnProfs(cpList), nil
}
func (cpm *ConnProfileMgr) save() error {
list, _ := cpm.GetConnProfileList()
b, err := json.MarshalIndent(list, "", " ")
if err != nil {
return util.NewNewtError(err.Error())
}
filename, err := connProfileCfgFilename()
if err != nil {
return err
}
err = ioutil.WriteFile(filename, b, 0644)
if err != nil {
return util.ChildNewtError(err)
}
return nil
}
func (cpm *ConnProfileMgr) DeleteConnProfile(name string) error {
if cpm.profiles[name] == nil {
return util.FmtNewtError("connection profile \"%s\" doesn't exist",
name)
}
delete(cpm.profiles, name)
err := cpm.save()
if err != nil {
return err
}
return nil
}
func (cpm *ConnProfileMgr) AddConnProfile(cp *ConnProfile) error {
cpm.profiles[cp.Name] = cp
err := cpm.save()
if err != nil {
return err
}
return nil
}
func (cpm *ConnProfileMgr) GetConnProfile(pName string) (*ConnProfile, error) {
// Each section is a connection profile, key values are the contents
// of that section.
p := cpm.profiles[pName]
if p == nil {
return nil, util.FmtNewtError("connection profile \"%s\" doesn't "+
"exist", pName)
}
return p, nil
}
func NewConnProfile() *ConnProfile {
return &ConnProfile{}
}
var globalConnProfileMgr *ConnProfileMgr
func GlobalConnProfileMgr() *ConnProfileMgr {
if globalConnProfileMgr == nil {
panic("connection profile manager not initialized")
}
return globalConnProfileMgr
}
func InitGlobalConnProfileMgr() error {
if globalConnProfileMgr != nil {
return util.NewNewtError("connection profile manager initialized twice")
}
var err error
globalConnProfileMgr, err = NewConnProfileMgr()
if err != nil {
return err
}
return nil
}