2016-07-05 00:20:17 +02:00
package main
2016-07-21 23:04:48 +02:00
// Create a new virtual serial device:
// socat PTY,link=/dev/ttyS10 PTY,link=/dev/ttyS11
2016-07-05 00:20:17 +02:00
import (
2016-07-12 22:52:48 +02:00
"log"
"os"
"path"
2016-07-05 00:20:17 +02:00
2016-07-12 22:52:48 +02:00
"github.com/fsnotify/fsnotify"
2016-07-21 23:04:48 +02:00
"github.com/tarm/serial"
2016-07-13 20:56:01 +02:00
"github.com/mkideal/cli"
2016-07-05 00:20:17 +02:00
)
2016-07-21 23:04:48 +02:00
// TODO: Make the error code optional (as a parameter)
2016-07-12 23:38:55 +02:00
func stop ( ) {
log . Println ( "Have a nice day." )
2016-07-21 23:04:48 +02:00
os . Exit ( 0 )
2016-07-12 23:38:55 +02:00
}
2016-07-21 23:04:48 +02:00
func waitAndExecuteCommandsFromDevice ( device string ) {
config := & serial . Config { Name : device , Baud : 115200 }
serial , err := serial . OpenPort ( config )
if err != nil {
log . Fatal ( err )
}
log . Printf ( "Open the connection to the n3rdpad over %s" , device )
// Read from serial
buffer := make ( [ ] byte , 128 )
for {
num , err := serial . Read ( buffer )
if err != nil {
log . Fatal ( err )
}
// TODO: Do something with the incomind commands
log . Printf ( "%q" , buffer [ : num ] )
}
2016-07-12 23:48:01 +02:00
}
2016-07-13 20:56:01 +02:00
func watchForConfigChanges ( configFile string ) {
2016-07-12 22:52:48 +02:00
watcher , err := fsnotify . NewWatcher ( )
if err != nil {
log . Fatal ( err )
}
defer watcher . Close ( )
2016-07-05 00:20:17 +02:00
2016-07-12 22:52:48 +02:00
done := make ( chan bool )
go func ( ) {
for {
select {
case event := <- watcher . Events :
2016-07-12 23:38:55 +02:00
// The file is changed. This is the only event we are interested
// in. If the file is renamed, removed or something else, we drop
// an error to the user.
2016-07-12 22:52:48 +02:00
if event . Op & fsnotify . Write == fsnotify . Write {
2016-07-12 23:38:55 +02:00
log . Println ( "Reload the config file ..." )
2016-07-12 23:48:01 +02:00
// TODO: Parse the config file
// TODO: Handle errors in the config file
// TODO: Write a mapping for the mapping of the keys to the binary format the avr wants.
// TODO: Establish a connection to the device
// TODO: Transfer the new key mappings
// TODO: Close the connection?
2016-07-12 23:38:55 +02:00
}
2016-07-21 23:04:48 +02:00
// TODO: vim has a very strange behaviour to save a file. There is
// no WRITE event triggered. Instead: RENAME -> CHMOD -> REMOVE is
// called on that file and after that, this mechanism lost track of
// the file. Why is that tha case? Cant find a valid answer to that.
2016-07-12 23:38:55 +02:00
if event . Op & fsnotify . Rename == fsnotify . Rename ||
event . Op & fsnotify . Remove == fsnotify . Remove {
2016-07-13 20:56:01 +02:00
log . Println ( "The configuration file is renamed or removed. We cant do any further changes without the config file. So create the file or rename it back and restart the agent." )
2016-07-12 23:38:55 +02:00
stop ( )
2016-07-12 22:52:48 +02:00
}
case err := <- watcher . Errors :
2016-07-13 20:56:01 +02:00
log . Println ( "We have the following problem with the configuration file: " , err )
2016-07-12 23:38:55 +02:00
log . Println ( "Try the fix this problem by yourself and restart the agent." )
stop ( )
2016-07-12 22:52:48 +02:00
}
}
} ( )
2016-07-05 00:20:17 +02:00
2016-07-13 20:56:01 +02:00
err = watcher . Add ( configFile )
2016-07-12 22:52:48 +02:00
if err != nil {
2016-07-13 20:56:01 +02:00
log . Fatal ( "Can't find the configuration file. Please create one." )
2016-07-12 22:52:48 +02:00
}
<- done
2016-07-05 00:20:17 +02:00
}
2016-07-13 20:56:01 +02:00
type argT struct {
cli . Helper
ConfigFile string ` cli:"c,config" usage:"specify a keymap config file" `
2016-07-21 23:04:48 +02:00
Device string ` cli:"d,device" usage:"specify the serial port, the n3rdpad is hooked to" `
2016-07-13 20:56:01 +02:00
}
2016-07-05 00:20:17 +02:00
func main ( ) {
2016-07-13 20:56:01 +02:00
configPath , _ := os . Getwd ( )
configFile := path . Join ( configPath , "keymap.conf" )
cli . Run ( & argT { } , func ( ctx * cli . Context ) error {
args := ctx . Argv ( ) . ( * argT )
if args . ConfigFile != "" {
configFile = args . ConfigFile
}
2016-07-21 23:04:48 +02:00
if args . Device == "" {
log . Fatal ( "You need to specify the serial device with the --device parameter." )
stop ( ) ;
}
2016-07-13 20:56:01 +02:00
if ! args . Help {
// Start up the application
log . Println ( "Using the configuration file" , configFile )
2016-07-21 23:04:48 +02:00
go watchForConfigChanges ( configFile )
waitAndExecuteCommandsFromDevice ( args . Device )
2016-07-13 20:56:01 +02:00
stop ( )
}
return nil
} )
2016-07-05 00:20:17 +02:00
}