ãã®ã¿ã¹ã¯ãçºçããèæ¯ã¯ãããããããšã§ããã顧客ãACSã³ã³ãããŒã©ãŒã®ç¹å¥ãªæ©èœãåãåããããšããèŠæã«ãããŸãã ãã®ç¹å®ã®æ©èœã¯æ¬¡ã®ãšããã§ãã
- ã³ã³ãããŒã©ãŒã¯ãããã¯ãŒã¯åãããŠããå¿ èŠããããŸãïŒããã¯ã®ãªãŒãã³ãã¯ããŒãºãããã³ãããŒãããã¯ãã¢ãŒãïŒ
- ãã¿ã³ã«ããééïŒããªã¬ãŒã¢ãŒãïŒ
- ããŒã«ããééïŒããªã¬ãŒã¢ãŒãïŒ
- å ¥å/åºåã®ããŒãããã¯ã¢ãŒã
- ããŒã®è¿œå ãèªã¿åããåé€
- ããŒããã¯
- ã€ãã³ããã°
ããŒãããã¯ã¢ãŒãã§ã¯ãããŒããã¿ã³ããŸãã¯HTTPã䜿çšããŠããã¯ãéãããšã¯ã§ããŸããã ç¡å¹åã¯ãããã¯ã¢ãŒãããã£ã³ã»ã«ããããã³ã³ãããŒã©ã®é»æºããªã»ããããããšã§çºçããŸãã
顧客ãã»ãšãã©ãã¹ãŠã®ãéãæãæºåãã§ããŠããããšãèãããšãæåã«ã³ã³ãããŒã©ãŒãéçºããèšç»ã¯ãããŸããã§ããããåžå Žã§æºåãã§ããŠããã³ã³ãããŒã©ãŒãèŠã€ããŠã¿ã¹ã¯ãå®çŸããããšã«ããŸããã ãããå®éã«ã¯ããã¹ãŠãããã»ã©æ¥œãããªãããšãå€æããŸããã æ確ã«ããããã«ã顧客ã®ãªãã£ã¹ã¯KNX + Control4ã«åºã¥ããèªååïŒã¹ããŒãããŒã ã·ã¹ãã ïŒãå®è£ ããŠãããšèšããªããã°ãªããŸããã
æ¢åã®ãããã¯ãŒã¯ã³ã³ãããŒã©ãŒã¯éåžžã«æ©èœçã§ãããã»ãšãã©ã®å Žåããã®æ©èœã¯è£œé å ã®ãã¡ãŒã ãŠã§ã¢ã«ãã£ãŠä¿è·ãããŠãããåœç¶å€æŽããããšã¯ã§ããŸããã ããšãã°ãç§ãã¡ã調ã¹ãã³ã³ãããŒã©ãŒã¯ã©ããïŒåºåãã¢ã³ãã¢ããã¿ã€ãºã®ããã«èŠããªãããã«ãªã¹ããæäŸããŸãããèšäºã®æå³ã§ã¯äžè¬çã«ã¯éèŠã§ã¯ãããŸããïŒããã¿ã³ã§ãã¢ãéããæ©èœã¯ãããŸããïŒç¢ºãã«ãäžéšã®ã³ã³ãããŒã©ãŒã¯å€åç§ãã¡ã¯ããããèŠéããïŒã ãããããããã¯ãŒã¯ã³ã³ãããŒã©ãŒã¯çè«çã«ã¯ãHTTPãä»ããŠééãå«ãããŸããŸãªã³ãã³ããåä¿¡ã§ããControl4ã³ã³ãããŒã©ãŒã¯ãããã®ã³ãã³ããéä¿¡ã§ããŸãã ããããæ€èšäžã®ã³ã³ãããŒã©ãŒã§äœ¿çšå¯èœãªSDKã¯ãã²ãŒããŠã§ã€ãšããŠWindows PCã䜿çšããããšãæ瀺ããŠããå€ãããŒãžã§ã³1,2,3ã®.NETã©ã€ãã©ãªãŒã«å®è£ ãããŠããŸãïŒ.NetCoreãMonoããªã©ïŒã 確ãã«ã.NetéçºãLinuxã«é©å¿ãããããšã¯ã§ããŸãããããã®æç¹ã§ã¯ããã®ã¢ãããŒãã®æ£ç¢ºæ§ãšå®å®æ§ã«èªä¿¡ããããŸããã§ããã
å¥ã®åé¡ã¯ãããŒã®ããã¯ã§ããã Ironlogicã®äºç®ã§ãã1ã€ã®ã³ã³ãããŒã©ãŒïŒäºç®ïŒç³è«è ã®1人ãæå®ãããŠãã ããïŒïŒã ããç°¡åã«ãã®ã¿ã¹ã¯ã«å¯ŸåŠããŸããã 圌ã«ã¯ãããªã¬ãŒãã¢ãŒãããããŸããããã¿ã³ã¯éãããã ãã®ãã®ã§ãã ãã¯ãã«ã«ãµããŒãããSDKã«é¢ããæ£ããæ å ±ãåãåããŸããã§ããã äžè¬ã«ããã¹ãŠã®æ å ±ãåæããã³è©äŸ¡ããçµæãç¬èªã®ãœãªã¥ãŒã·ã§ã³ãéçºããããšã決å®ãããŸããã
ããŒããŠã§ã¢ãã©ãããã©ãŒã ãšããŠãRaspberry PiïŒrev.BïŒ+ Arduino Nanoã䜿çšããããšã«ããŸããã Arduinoã¯äœã¬ãã«ããã³ã€ã³ã¿ãŒãã§ã€ã¹ã§æ£åžžã«åäœãããMalinkaãã§ã¯ãæ¬æ Œçãªãããã¯ãŒã¯ã¹ã¿ãã¯ãäœæããé«ã¬ãã«ã®ããã°ã©ãã³ã°èšèªã䜿çšã§ããŸãã ããŒãéã®éä¿¡ã¯USBçµç±ïŒã·ãªã¢ã«ããŒãçµç±ïŒ
Arduinoã®ã³ãŒãã«å®è£ ãåæ ãããŠãããµãŠã³ã衚瀺èŠçŽ ïŒãµãŠã³ãã¹ããŒã«ãŒïŒã¯ããã®å³ã«ã¯ç€ºãããŠããŸããã ã³ãŒãããããã³ã«æ¥ç¶ãããŠããããšãããããŸã-9ã
次ã®ã³ã³ããŒãã³ããå®è£ ã«äœ¿çšãããŸããã
â¢Raspberry PiïŒrevãBïŒ-1å
â¢Arduino Nano-1å
â¢ãµãŠã³ãã¹ããŒã«ãŒ-1åã
â¢ã¿ããã¡ã¢ãªããŒãªãŒããŒïŒiButtonïŒ-1åã
â¢æµæ220ãªãŒã -1 tã
â¢12Vãªã¬ãŒ-1åã
â¢é»ç£ããã¯12V-1åã
éçºç°å¢ã®èŠä»¶
Goã§éçºããåã«ãç°å¢ãæºåããå¿ èŠããããŸãïŒWindowsã§éçºãè¡ã£ããããäŸåé¢ä¿ã®ãªã¹ãã¯ãã®OSå°çšã«èª¬æãããŠããŸãïŒã åé ç®ã«ã€ããŠè©³ããã¯èª¬æããŸããã ãããã«ã€ããŠã¯ãã§ã«å€ãã®ããšãè¿°ã¹ãããæžãããŠããŸãã
- Windowsã«Goãã€ã³ã¹ããŒã«ãã
- éçºããŒã«ãã€ã³ã¹ããŒã«ããŸãã Visual Studio Codeã䜿çšããŸããã éåžžã«äŸ¿å©ã§æ©èœçãªã³ãŒããšãã£ã¿ãŒã ãå§ãã§ãïŒ Goã«ã¯JetBrains Goland IDEã䜿çšã§ããŸãã
- Goã§åäœããããã«Visual Studioã³ãŒããèšå®ããŸãã æ瀺ã¯è±èªã§ããããã¹ãŠãéåžžã«æ確ã«èª¬æãããŠããŸãã
- Arduino IDEãã€ã³ã¹ããŒã«ããŸãã-ã¹ã±ãããåããŸãã
- GitãªããžããªããŒã«ïŒGithubããGoããã±ãŒãžãããŠã³ããŒãããããïŒ
Arduinoçšã¹ã±ããSKUD
Arduinoã®ã³ãŒãã¯éåžžã«ã·ã³ãã«ã§ç°¡åã§ãã 泚æããå¿ èŠãããã®ã¯ãOneWireã©ã€ãã©ãªãæšæºã»ããã«å«ãŸããŠãããã ããŠã³ããŒãããå¿ èŠããããšããããšã ãã§ãã
ã³ãŒãã®å°ããªç¹åŸŽã¯ããã€ã¯ãã³ã³ãããŒã©ã®EEPROMã«ããã¯ã®çŸåšã®ç¶æ ãä¿åããããšã§ããããã«ãããçãæ éãé»åæ倱ãçºçããå Žåã«ããã¯ã®çŸåšã®ç¶æ ãèšæ¶ã§ããŸãã
Arduinoçšã¹ã±ããSKUD
#include <OneWire.h> #include <EEPROM.h> #define RELAY1 6 // boolean isClose; // boolean hl=false; // byte i; OneWire ds(7); // byte addr[8]; // String inCommand = ""; // Raspberry Pi char character; // void setup() { Serial.begin(9600); pinMode(RELAY1, OUTPUT); stateRead(); } void loop(){ if (ds.search(addr)) { ds.reset_search(); if ( OneWire::crc8( addr, 7) != addr[7]) { } else { if(!hl){ for( i = 0; i < 8; i++) { Serial.print(addr[i],HEX); } Serial.println(); } } } ds.reset(); delay(500); while(Serial.available()) { character = Serial.read(); inCommand.concat(character); } if (inCommand=="hlock1"){ hl=true; r_close(); Serial.println("HardLock Enable"); } if (inCommand=="hlock0"){ hl=false; Serial.println("HardLock Disable"); } if (inCommand != "" && !hl) { if ((inCommand=="open") && (isClose) ){ r_open(); } if ((inCommand=="close") &&(!isClose)){ r_close(); } } inCommand=""; } void r_open(){ digitalWrite(RELAY1,LOW); isClose=false; stateSave(isClose); SoundTone(0); delay(100); Serial.println("Relay Open "); } void r_close(){ digitalWrite(RELAY1,HIGH); isClose=true; stateSave(isClose); SoundTone(1); delay(100); Serial.println("Realy Close"); } void stateSave(boolean st) // EEPROM { if (st) { int val=1; EEPROM.write(0,val); } else { int val=0; EEPROM.write(0,val); } } void stateRead() { int val; val= (EEPROM.read(0)); if (val==1) r_close(); else r_open(); } void SoundTone(boolean cmd){ if(!cmd){ for (int i=0;i<10;i++){ tone(9, 815, 100); delay(250); } } else { for (int i=0;i<4;i++){ tone(9, 395, 500); delay(350); } } noTone(9); }
æ¢ã«è¿°ã¹ãããã«ãã¡ã€ã³ã³ã³ãããŒã©ãŒã³ãŒãã¯Goã§èšè¿°ãããŠããŸãã ã»ãšãã©ãã¹ãŠã®ã©ã€ãã©ãªã¯ã2ã€ã®äŸå€ãé€ããæšæºã®GoãœãŒã¹ããååŸãããŸãã
æåã¯ãkey \ valueãªã©ã®ã¡ã€ã³BoltDBããŒã¿ããŒã¹ã§ãã ãããšåãããšã¯ãã¿ã³ããªã³ãšèžãããšããå¿ èŠãšããªããããã¯éåžžã«ç°¡åã§éãã 2çªç®ã®å®è£ ã¯ãCOMããŒãã§åäœããŸãã
ã¡ã€ã³ã³ã³ãããŒã©ãŒã®åäœã¢ã«ãŽãªãºã ã¯æ¬¡ã®ãšããã§ãã
- èµ·åæã«ãæ§æã¯config.jsonãã¡ã€ã«ããèªã¿åãããŸãã
- å°ããªHTTP RESTãµãŒãã¹ãéå§ãããŸãã
- COMããŒããéããArduinoãšããŒã¿ã亀æããŸãã
- ã¿ã€ãboolã®ãã£ãã«ãäœæãããCOMããŒããžã®ãã€ã³ã¿ãŒãšãšãã«ãGodurouã«éä¿¡ãããããã§Arduinoããã®ããŒã®IDãèªã¿åãããŸãã
- 次ã«ããµã€ã¯ã«ãéå§ãããå ã«éä¿¡ããããã£ãã«ããã®ããŒã¿ãåŸ æ©ã«ãŒãã³ã«éãããŸãã èªã¿åãããŒãããŒã¿ããŒã¹ã«ååšããã¢ã¯ãã£ãã§ããå Žåã«ã®ã¿ããã£ãã«ã§ããŒã¿ãåä¿¡ãããŸãããã®åŸããªã¬ãŒã¹ã€ããã³ã°ã³ãã³ããArduinoã«éä¿¡ãããŸãã
ããŒã®è¿œå ãåé€ãèªã¿åããããã³ããã¯ã®ç®¡çã¯ãHTTPãªã¯ãšã¹ããä»ããŠè¡ãããŸãã å€ãã®äººã¯ãããã¯æãã ãšããã«èšãã§ãããã 誰ã§ãã³ã³ãããŒã©ãŒãžã®èŠæ±ãæºããããšãã§ããŸãã ã¯ããã»ãã¥ãªãã£ãããã«éçºããå¿ èŠãããããšã«åæããŸãããäºé²çãšããŠãæ§æãã¡ã€ã«ã«ã¯ããŸããŸãªããŒã ã®ãšã³ããã€ã³ãã®ååãå€æŽããæ©èœããããŸãã éšå€è ã«ããã³ã³ãããŒã©ãŒã®å¶åŸ¡ãææ¡ããã®ã¯å°ãé£ããã§ãã
ã³ã³ãããŒã©ãŒã³ãŒã
package main import ( "bufio" "encoding/json" "io/ioutil" "fmt" "log" "net/http" "os" "regexp" "time" "github.com/boltdb/bolt" "github.com/tarm/serial" ) const dbname = "access.db" // var isOpen, isHLock bool = false, false var serialPort *serial.Port func main() { // config, err := readConfig() if err != nil { fmt.Printf("Error read config file %s", err.Error()) return } // f, err := os.OpenFile(config.LogFilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { log.Fatalf("error opening file: %v", err) } defer f.Close() log.SetOutput(f) // HTTP- http.HandleFunc("/"+config.NormalModeEndpoint, webNormalMode) http.HandleFunc("/"+config.HardLockModeEndpoint, webHLockMode) http.HandleFunc("/"+config.CloseEndpoint, webCloseRelay) http.HandleFunc("/"+config.OpenEndpoint, webOpenRelay) http.HandleFunc("/"+config.AddKeyEndpoint, addKey) http.HandleFunc("/"+config.ReadKeysEndpoint, readKeys) http.HandleFunc("/"+config.DeleteKeyEndpoint, deleteKey) go http.ListenAndServe(":"+config.HTTPPort, nil) log.Printf("Listening on port %s...", config.HTTPPort) // db, err := bolt.Open(dbname, 0600, nil) if err != nil { log.Fatal(err) } db.Close() // Serial c := &serial.Config{Name: config.SerialPort, Baud: 9600} s, err := serial.OpenPort(c) if err != nil { fmt.Printf("Error open serial port %s ", err.Error()) log.Fatal(err) } serialPort = s // , go- ch := make(chan bool) // wait chanel until key is valid go getData(ch, s) for { time.Sleep(time.Second) tmp := <-ch if tmp { if isOpen { closeRelay() } else { openRelay() } } } } func getData(ch chan bool, s *serial.Port) { for { reader := bufio.NewReader(s) reply, err := reader.ReadBytes('\n') if err != nil { log.Fatal(err) } k := string(reply) if chk := checkKey(k); chk { ch <- chk time.Sleep(2 * time.Second) } } } func invertBool() { // isOpen = !isOpen } func checkErr(err error) { if err != nil { panic(err) } } func boltStore(value Key) { db, err := bolt.Open(dbname, 0600, nil) if err != nil { log.Fatal(err) } defer db.Close() db.Update(func(tx *bolt.Tx) error { b, err := tx.CreateBucketIfNotExists([]byte("keys")) if err != nil { return err } return b.Put([]byte(value.Key), []byte(value.isEnable)) }) } func boltRead(key string) bool { var strKey string db, err := bolt.Open(dbname, 0600, nil) if err != nil { log.Fatal(err) return false } defer db.Close() db.View(func(tx *bolt.Tx) error { re := regexp.MustCompile(`\r\n`) key := re.ReplaceAllString(key, "") re = regexp.MustCompile(`\n`) key = re.ReplaceAllString(key, "") re = regexp.MustCompile(`\r`) key = re.ReplaceAllString(key, "") log.Printf("Readed key: %s\n", key) b := tx.Bucket([]byte("keys")) v := b.Get([]byte(key)) strKey = string(v) return nil }) if strKey == "1" { log.Printf("Key %s valid\n", key) return true } return false } func addKey(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() var key Key key.Key = params.Get("key") key.isEnable = params.Get("enable") boltStore(key) log.Printf("You add the key %s", key.Key) fmt.Fprintln(w, "You add the key", key.Key) } func readKeys(w http.ResponseWriter, r *http.Request) { keys := make(map[string]string) db, err := bolt.Open(dbname, 0600, nil) if err != nil { log.Fatal(err) } defer db.Close() db.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte("keys")) b.ForEach(func(k, v []byte) error { keys[string(k)] = string(v) fmt.Printf("map: %s\n", keys[string(k)]) return nil }) return nil }) data, _ := json.Marshal(keys) fmt.Fprintln(w, string(data)) } func deleteKey(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() deleteKey := params.Get("key") db, err := bolt.Open(dbname, 0600, nil) if err != nil { log.Fatal(err) } defer db.Close() db.Update(func(tx *bolt.Tx) error { // Retrieve the users bucket. // This should be created when the DB is first opened. b := tx.Bucket([]byte("keys")) err := b.Delete([]byte(deleteKey)) if err != nil { fmt.Printf("Key: \"%s\" delete failed: %s\n", deleteKey, err.Error()) return err } fmt.Fprintf(w, "Key: \"%s\" deleted succesfully\n", deleteKey) // Persist bytes to users bucket. return nil }) } func webNormalMode(w http.ResponseWriter, r *http.Request) { isHLock = false _, err := serialPort.Write([]byte("hlock0")) if err != nil { log.Fatal(err) } fmt.Fprintln(w, "Normal Mode") } func webHLockMode(w http.ResponseWriter, r *http.Request) { _, err := serialPort.Write([]byte("hlock1")) if err != nil { log.Fatal(err) } isHLock = true fmt.Fprintln(w, "HardLock Mode") } func webCloseRelay(w http.ResponseWriter, r *http.Request) { switchRelay() fmt.Fprintln(w, "switch relay") } func webOpenRelay(w http.ResponseWriter, r *http.Request) { openRelay() fmt.Fprintln(w, "open lock") } func closeRelay() { _, err := serialPort.Write([]byte("close")) if err != nil { log.Fatal(err) } invertBool() log.Println("Close") } func openRelay() { _, err := serialPort.Write([]byte("open")) if err != nil { log.Fatal(err) } invertBool() log.Println("Open") } func switchRelay() { if isOpen { closeRelay() } else { openRelay() } } func checkKey(key string) bool { if boltRead(key) { return true } return false } func readConfig() (*Config, error) { plan, _ := ioutil.ReadFile("config.json") config := Config{} err := json.Unmarshal([]byte(plan), &config) return &config, err }
Raspberry Pièªäœã«ãã€ããªãã¡ã€ã«ãã¢ã»ã³ãã«ããŸããïŒåœç¶ãGoã®ãã¹ãŠã®äŸåé¢ä¿ããã©ãºããªãŒãã«ã€ã³ã¹ããŒã«ããå¿ èŠããããŸããïŒã
GOOS=linux GOARCH=arm go build -o /home/pi/skud-go/skud-go
ãŸããäž»ãªããšã¯ããã€ããªãã¡ã€ã«ã«æ¬¡ã®äŸåãã¡ã€ã«ã眮ãããšãå¿ããªãããšã§ãã
config.json access.db
config.json
{
ãSerialPortãïŒã/ dev / ttyUSB0ãã
ãHttpPortãïŒã80ãã
ãNormalModeEndpointãïŒãéåžžãã
ãHardLockModeEndpointãïŒãblockãã
ãCloseEndpointãïŒãcloseãã
ãOpenEndpointãïŒãopenãã
AddKeyEndpointïŒaddkey
DeleteKeyEndpointïŒdeletekey
ãReadKeysEndpointãïŒãreadkeysãã
ãLogFilePathãïŒã/ var / log / skud-go.logã
}
ãSerialPortãïŒã/ dev / ttyUSB0ãã
ãHttpPortãïŒã80ãã
ãNormalModeEndpointãïŒãéåžžãã
ãHardLockModeEndpointãïŒãblockãã
ãCloseEndpointãïŒãcloseãã
ãOpenEndpointãïŒãopenãã
AddKeyEndpointïŒaddkey
DeleteKeyEndpointïŒdeletekey
ãReadKeysEndpointãïŒãreadkeysãã
ãLogFilePathãïŒã/ var / log / skud-go.logã
}
ã³ã³ãããŒã©ãŒã®ããŒã¿åã skud_type.go
package main //Key type Key struct { Key string isEnable string } //Config type Config struct { SerialPort string `json:"serialPort"` HTTPPort string `json:"httpPort"` NormalModeEndpoint string `json:"normalModeEndpoint"` HardLockModeEndpoint string `json:"hardLockModeEndpoint"` CloseEndpoint string `json:"closeEndpoint"` OpenEndpoint string `json:"openEndpoint"` AddKeyEndpoint string `json:"addKeyEndpoint"` DeleteKeyEndpoint string `json:"deleteKeyEndpoint"` ReadKeysEndpoint string `json:"readKeysEndpoint"` LogFilePath string `json:"logFilePath"` }
ã³ã³ãããŒã©ããµãŒãã¹ãšããŠéå§ããã«ã¯ãè¿œå ã®ãŠããããã¡ã€ã«ãäœæããå¿ èŠããããŸãã ãã®ãããªãã¡ã€ã«ã¯ãç¹å®ã®ãªãœãŒã¹ã®ç®¡çæ¹æ³ãsystemdåæåã·ã¹ãã ã«äŒããŸãã ãµãŒãã¹-ããã°ã©ã ã®éå§ãšåæ¢ã®äŸåé¢ä¿ãšãã©ã¡ãŒã¿ãŒãå®çŸ©ããæãäžè¬çãªã¿ã€ãã®ãŠããããã¡ã€ã«ã
skud-goçšã®ãã®ãããªãã¡ã€ã«ãäœæããŸãã ãã¡ã€ã«ã¯skud-go.serviceãšåŒã°ãã/ etc / systemd / systemã«ä¿åãããŸãã
sudo nano /etc/systemd/system/skud-go.service
ãã¡ã€ã«ã®å 容ïŒ
[Unit] Description=Access Control System Controller by Go After=network.target [Service] User=pi ExecStart=/home/pi/skud-go/skud-go [Install] WantedBy=multi-user.target
æ°ãããµãŒãã¹ãéå§ããã«ã¯ã次ãå ¥åããŸãã
sudo systemctl start skud-go
次ã«ããã®ãµãŒãã¹ã®èªåå®è¡ãæå¹ã«ããå¿ èŠããããŸãã
sudo systemctl enable skud-go
ãã®çµæã6ãæ以äžã«ããã£ãŠãéåžžã«ã·ã³ãã«ã§æ©èœçãªã¢ããã¿ã€ã ã³ã³ãããŒã©ãŒãå®çŸããŸããïŒãã¡ããããã¹ãŠãå ãè¡ã£ãŠããŸãïŒã ãã®èšäºã誰ãã«åœ¹ç«ã€ããšãé¡ã£ãŠããŸãã
â Githubã§å ¥æå¯èœãªãœãŒã¹