From 5a08364ad399bcadb7c9914d86518ff541783f1b Mon Sep 17 00:00:00 2001
From: MaMe82 <mame8282@googlemail.com>
Date: Thu, 15 Nov 2018 08:01:42 +0100
Subject: [PATCH] Init state from DB instead of script

---
 dist/db/init.db            | Bin 0 -> 1319 bytes
 service/bluetooth.go       |  13 +++++++--
 service/datastore/store.go |  30 +++++++++++++++++---
 service/rpc_server.go      |  56 +++++++++++++++++++++++++++++++------
 service/service.go         |  19 +++++--------
 5 files changed, 90 insertions(+), 28 deletions(-)
 create mode 100644 dist/db/init.db

diff --git a/dist/db/init.db b/dist/db/init.db
new file mode 100644
index 0000000000000000000000000000000000000000..4e86b429ab149c6cb3572c463f62d180493593d9
GIT binary patch
literal 1319
zcmchX&u<bz6vy}RW1$1IbmD<-#H_^BhD5r%z(V%aa4>4phNLmki@0>Bp$QOV7r}Z_
zNiXWDO?uLDs(*k7<KM$kFZ>D4>@eM8+jw)6&Cb02&U>Ht_PyPg_=Ql@Yq*}>_Xa(@
ziykBS=l$Qm!sB!-vy!_ThcskBg$>Z43S009>hKI+LJN8@f_DJ<B$F_~7ByRPy)^9B
zbtc0yis;2+MFB~LZz9?%IdB_Ik9e(%pq~ImeM>r|AiZJ~46~pW^jyj)mkZ+7Ho&kk
z*C}h8UZ=O|blr~azT(~rZDPB`wX!I1Vc^7tJ3~`K<xXumF5^I;(|!2zz6y*sbSh{u
zqaC=-%eZfm%q;>}=eR2Z)qj?%6nF>ErHZmZ%+Cwt+Z@?<V{jV2_K72uP^v{Jx5Vkf
zXM!%v=!R{(tBG1RoYr2ivDZEzT@Q~?)PI?Vd09)>mvsko-Ct$(&kDvnh?mlLq0Q^c
zHuJh(p^W^K(k1=Zq#sa<kN-a@qXSXPW!g#}>5D?*7bqr%LM#-q$caThwb04=<;7OX
zuU+$Tc-pMZ<o6<Y!n56r$Q^Vq12yR*WYNv%(}33FbTXgZsN+pQb+_W74CJN5Btr9y
z3T_LF6c|YCy8ubj1Ok#T5T{eDjdaIsD(qP-RdVvSy-lh{KFudxZN5>t#Yj5DcAA9j
zv#Do4i~c%VEg6<sw9K-l8&<Jol}#L&$|f`E#$li{uj)*Ci0eK;0xu1^4%t8G5{Hq;
zp9^v{47eYn7}eN=wx@)i?y8{4mX6ff<oJ9xIi>gUxjH>Lnx2iPC!eP$<JshBGX44k
Pr+6L@cw#k)1z7q6=;cc|

literal 0
HcmV?d00001

diff --git a/service/bluetooth.go b/service/bluetooth.go
index 2e6d4e1..c201cd3 100644
--- a/service/bluetooth.go
+++ b/service/bluetooth.go
@@ -30,6 +30,8 @@ type BtService struct {
 	BrName           string
 	//bridgeIfDeployed bool
 
+	defaultSettings *pb.BluetoothSettings //This settings are changed if the BluetoothService isn't up, but settings are deployed (Master Template on startup)
+
 	Agent *bluetooth.DefaultAgent
 
 	serviceAvailableLock *sync.Mutex
@@ -70,6 +72,7 @@ func NewBtService(rootService *Service, retryTimeout time.Duration) (res *BtServ
 		Agent:   bluetooth.NewDefaultAgent("1337"),
 		BrName:  BT_ETHERNET_BRIDGE_NAME,
 		serviceAvailableLock: &sync.Mutex{},
+		defaultSettings:GetDefaultBluetoothSettings(),
 	}
 
 	log.Println("Starting Bluetooth sub system...")
@@ -101,12 +104,12 @@ func NewBtService(rootService *Service, retryTimeout time.Duration) (res *BtServ
 			res.Agent.Start(toolz.AGENT_CAP_NO_INPUT_NO_OUTPUT)
 
 			// Deploy default settings
-			defaultSettings := GetDefaultBluetoothSettings()
-			_,err := res.DeployBluetoothControllerInformation(defaultSettings.Ci)
+
+			_,err := res.DeployBluetoothControllerInformation(res.defaultSettings.Ci)
 			if err != nil {
 				log.Println("Not able to deploy default bluetooth settings: ", err.Error())
 			} else {
-				_,err = res.DeployBluetoothAgentSettings(defaultSettings.As)
+				_,err = res.DeployBluetoothAgentSettings(res.defaultSettings.As)
 				if err != nil {
 					log.Println("Not able to deploy default bluetooth agent settings: ", err.Error())
 				}
@@ -119,6 +122,10 @@ func NewBtService(rootService *Service, retryTimeout time.Duration) (res *BtServ
 	return
 }
 
+func (bt *BtService) ReplaceDefaultSettings(s *pb.BluetoothSettings) {
+	bt.defaultSettings = s
+}
+
 func (bt *BtService) Stop() {
 	bt.Agent.Stop() // unregister the agent again
 	if ci,err := bt.Controller.ReadControllerInformation(); err == nil {
diff --git a/service/datastore/store.go b/service/datastore/store.go
index 45039f8..df87b57 100644
--- a/service/datastore/store.go
+++ b/service/datastore/store.go
@@ -32,17 +32,39 @@ type Store struct {
 	serializer Serializer
 }
 
-func (s *Store) Open() (err error) {
+func exists(path string) (bool, error) {
+	_, err := os.Stat(path)
+	if err == nil {
+		return true, nil
+	}
+	if os.IsNotExist(err) {
+		return false, nil
+	}
+	return true, err
+}
+
+func (s *Store) Open(initDbBackupPath string) (err error) {
 	badgerOpts := badger.DefaultOptions
 	badgerOpts.Dir = s.Path
 	badgerOpts.ValueDir = s.Path
 	badgerOpts.SyncWrites = true
 	badgerOpts.TableLoadingMode = options.FileIO
 	badgerOpts.ValueLogLoadingMode = options.FileIO
+
+	// check if DB dir exists
+	exists,err := exists(s.Path)
+	if err != nil { return err }
+
 	s.Db, err = badger.Open(badgerOpts)
 	if s.serializer == nil {
 		s.serializer = NewSerializerProtobuf(false)
 	}
+
+	//If the s.Path didn't exist, we have a clean and empty DB at this point and thus restore a initial db
+	if !exists {
+		err = s.Restore(initDbBackupPath, true)
+	}
+
 	return err
 }
 
@@ -314,11 +336,11 @@ func (s *Store) DeleteMulti(keys []string) (err error) {
 	return nil
 }
 
-func Open(path string) (store *Store, err error) {
+func Open(workPath string, initDbBackupPath string) (store *Store, err error) {
 	store = &Store{
-		Path: path,
+		Path: workPath,
 	}
-	if err = store.Open(); err != nil {
+	if err = store.Open(initDbBackupPath); err != nil {
 		return nil, err
 	}
 	return
diff --git a/service/rpc_server.go b/service/rpc_server.go
index 8e98e11..1be4be7 100644
--- a/service/rpc_server.go
+++ b/service/rpc_server.go
@@ -10,6 +10,7 @@ import (
 	"github.com/mame82/P4wnP1_go/common"
 	"github.com/mame82/P4wnP1_go/common_web"
 	pb "github.com/mame82/P4wnP1_go/proto"
+	"github.com/mame82/P4wnP1_go/service/bluetooth"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 	"io"
@@ -77,30 +78,64 @@ func (s *server) GetAvailableGpios(context.Context, *pb.Empty) (res *pb.StringMe
 func (s *server) DeployMasterTemplate(ctx context.Context, mt *pb.MasterTemplate) (e *pb.Empty, err error) {
 	e = &pb.Empty{}
 
+	fmt.Println("Deploying master template ...")
+
 	//ignore templates with name of length 0
 	if len(mt.TemplateNameTriggerActions) > 0 {
+		fmt.Printf("... deploying TriggerActions '%s' ...\n", mt.TemplateNameTriggerActions)
 		_,err = s.DeployStoredTriggerActionSetReplace(ctx, &pb.StringMessage{Msg: mt.TemplateNameTriggerActions})
-		if err != nil { return }
-
+		if err != nil {
+			fmt.Printf("... error deploying TriggerActions '%s'\n", mt.TemplateNameTriggerActions)
+			return
+		}
+		fmt.Printf("... succeeded deploying TriggerActions '%s'\n", mt.TemplateNameTriggerActions)
 	}
 
 	for _,nnw := range mt.TemplateNamesNetwork {
+		fmt.Printf("... deploying Network Interface Settings '%s' ...\n", nnw)
 		_,err = s.DeployStoredEthernetInterfaceSettings(ctx, &pb.StringMessage{Msg: nnw})
-		if err != nil { return }
+		if err != nil {
+			fmt.Printf("... error deploying Network Interface Settings '%s'\n", nnw)
+			return
+		}
+		fmt.Printf("... succeeded deploying Network Interface Settings '%s'\n", nnw)
 	}
 
 	if len(mt.TemplateNameBluetooth) > 0 {
-		_, err = s.DeployStoredBluetoothSettings(ctx, &pb.StringMessage{Msg: mt.TemplateNameBluetooth})
-		if err != nil { return }
+		fmt.Printf("... deploying Bluetooth settings '%s' ...\n", mt.TemplateNameBluetooth)
+		_, btErr := s.DeployStoredBluetoothSettings(ctx, &pb.StringMessage{Msg: mt.TemplateNameBluetooth})
+		if btErr != nil {
+			if btErr == bluetooth.ErrBtSvcNotAvailable {
+				fmt.Printf("... ignoring Bluetooth error '%s'\n", mt.TemplateNameBluetooth)
+
+			} else {
+				fmt.Printf("... error deploying Bluetooth settings '%s'\n", mt.TemplateNameBluetooth)
+				return
+			}
+			fmt.Printf("... error deploying Bluetooth settings '%s'\n", mt.TemplateNameBluetooth)
+		}
+		fmt.Printf("... succeeded deploying Bluetooth settings '%s'\n", mt.TemplateNameBluetooth)
 	}
 	if len(mt.TemplateNameUsb) > 0 {
+		fmt.Printf("... deploying USB settings '%s' ...\n", mt.TemplateNameUsb)
 		_, err = s.DeployStoredUSBSettings(ctx, &pb.StringMessage{Msg: mt.TemplateNameUsb})
-		if err != nil { return }
+		if err != nil {
+			fmt.Printf("... error deploying USB settings '%s'\n", mt.TemplateNameUsb)
+			return
+		}
+		fmt.Printf("... succeeded deploying USB settings '%s'\n", mt.TemplateNameUsb)
 	}
 	if len(mt.TemplateNameWifi) > 0 {
+		fmt.Printf("... deploying WiFi settings '%s' ...\n", mt.TemplateNameWifi)
 		_, err = s.DeployStoredWifiSettings(ctx, &pb.StringMessage{Msg: mt.TemplateNameWifi})
-		if err != nil {	return }
+		if err != nil {
+			fmt.Printf("... error deploying WiFi settings '%s'\n", mt.TemplateNameWifi)
+			return
+		}
+		fmt.Printf("... succeeded deploying WiFi settings '%s'\n", mt.TemplateNameWifi)
 	}
+
+	fmt.Println("... master template deployed successfully")
 	return
 }
 
@@ -206,6 +241,9 @@ func (s *server) FireActionGroupSend(ctx context.Context, gs *pb.ActionGroupSend
 
 func (s *server) DeployBluetoothSettings(ctx context.Context, settings *pb.BluetoothSettings) (resultSettings *pb.BluetoothSettings, err error) {
 	defer s.rootSvc.SubSysEvent.Emit(ConstructEventNotifyStateChange(common_web.STATE_CHANGE_EVT_TYPE_BLUETOOTH))
+	//Overwrite default settings, in case the bluetooth sub system comes up later
+	s.rootSvc.SubSysBluetooth.ReplaceDefaultSettings(settings)
+
 	as := settings.As
 	ci := settings.Ci
 	resultSettings = &pb.BluetoothSettings{}
@@ -805,7 +843,7 @@ func (s *server) GetAllDeployedEthernetInterfaceSettings(ctx context.Context, em
 
 func (s *server) DeployEthernetInterfaceSettings(ctx context.Context, es *pb.EthernetInterfaceSettings) (empty *pb.Empty, err error) {
 	defer s.rootSvc.SubSysEvent.Emit(ConstructEventNotifyStateChange(common_web.STATE_CHANGE_EVT_TYPE_NETWORK))
-	log.Printf("Trying to deploy ethernet interface settings %v", es)
+	log.Printf("Trying to deploy ethernet interface settings %v\n", es)
 
 	empty = &pb.Empty{}
 	iname := es.Name
@@ -814,7 +852,7 @@ func (s *server) DeployEthernetInterfaceSettings(ctx context.Context, es *pb.Eth
 
 	err = nim.DeploySettings(es)
 	if err != nil {
-		log.Printf("Error deploying ethernet interface settings %v", err)
+		log.Printf("Error deploying ethernet interface settings %v\n", err)
 	}
 	return
 }
diff --git a/service/service.go b/service/service.go
index 48dc315..dbebef0 100644
--- a/service/service.go
+++ b/service/service.go
@@ -3,6 +3,8 @@
 package service
 
 import (
+	"context"
+	"fmt"
 	"github.com/mame82/P4wnP1_go/common_web"
 	pb "github.com/mame82/P4wnP1_go/proto"
 	"github.com/mame82/P4wnP1_go/service/datastore"
@@ -129,7 +131,7 @@ type Service struct {
 func NewService() (svc *Service, err error) {
 	svc = &Service{}
 
-	svc.SubSysDataStore, err = datastore.Open(PATH_DATA_STORE)
+	svc.SubSysDataStore, err = datastore.Open(PATH_DATA_STORE, PATH_DATA_STORE_BACKUP + "/init.db")
 	if err != nil {
 		return nil, err
 	}
@@ -175,20 +177,13 @@ func (s *Service) Start() {
 	s.SubSysTriggerActions.Start()
 
 	// Register TriggerActions
+	/*
 	log.Println("Register default TriggerActions ...")
 	RegisterDefaultTriggerActions(s.SubSysTriggerActions)
-
-	/*
-	// ToDo: 1) Manual start of BT NAP, has to be replaced by settings based approach (same as other subsystems)
-	// ToDo: 2) create a signal based method s.SubSysBluetooth.WaitTillServiceUp(timeout duration)
-	go func() {
-		timeStart := time.Now()
-		for timeSinceStart := time.Since(timeStart); !s.SubSysBluetooth.IsServiceAvailable() && timeSinceStart < time.Second*120 ;timeSinceStart = time.Since(timeStart) {
-			time.Sleep(time.Second)
-		}
-		s.SubSysBluetooth.StartNAP()
-	}()
 	*/
+	fmt.Println("Trying to deploy master template...")
+	_,err := s.SubSysRPC.DeployStoredMasterTemplate(context.Background(), &pb.StringMessage{Msg:"startup"})
+	fmt.Println("...!!!!! MASTER TEMPLATE:", err)
 
 	// fire service started Event
 	log.Println("Fire service started event ...")