gobm65.go
changeset 2 2452d9b23ec1
parent 1 05b31eb60d27
child 3 429d7e612cfd
equal deleted inserted replaced
1:05b31eb60d27 2:2452d9b23ec1
     1 package main
     1 package main
     2 
     2 
     3 import (
     3 import (
       
     4 	"encoding/json"
     4 	"fmt"
     5 	"fmt"
     5 	"io"
     6 	"io"
       
     7 	"io/ioutil"
     6 	"log"
     8 	"log"
     7 
     9 
       
    10 	flag "github.com/docker/docker/pkg/mflag"
     8 	"github.com/tarm/serial"
    11 	"github.com/tarm/serial"
     9 )
    12 )
    10 
    13 
    11 type measurement struct {
    14 type measurement struct {
    12 	header    int
    15 	Header    int
    13 	systolic  int
    16 	Systolic  int
    14 	diastolic int
    17 	Diastolic int
    15 	pulse     int
    18 	Pulse     int
    16 	month     int
    19 	Month     int
    17 	day       int
    20 	Day       int
    18 	hour      int
    21 	Hour      int
    19 	minute    int
    22 	Minute    int
    20 	year      int
    23 	Year      int
    21 }
    24 }
    22 
    25 
    23 func getData(s io.ReadWriteCloser, buf []byte, size int) (int, error) {
    26 func getData(s io.ReadWriteCloser, buf []byte, size int) (int, error) {
    24 	t := 0
    27 	t := 0
    25 	b := buf
    28 	b := buf
    33 		t = t + n
    36 		t = t + n
    34 	}
    37 	}
    35 	return t, nil
    38 	return t, nil
    36 }
    39 }
    37 
    40 
    38 func main() {
    41 func fetchData(dev string) (items []measurement, err error) {
    39 	c := &serial.Config{Name: "/dev/ttyUSB0", Baud: 4800}
    42 	c := &serial.Config{Name: dev, Baud: 4800}
    40 	s, err := serial.OpenPort(c)
    43 
    41 	if err != nil {
    44 	var s *serial.Port
    42 		log.Fatal(err)
    45 	s, err = serial.OpenPort(c)
    43 		return
    46 	if err != nil {
    44 	}
    47 		return items, err
    45 
    48 	}
       
    49 
       
    50 	// =================== Handshake =====================
    46 	q := []byte("\xaa")
    51 	q := []byte("\xaa")
    47 	//log.Printf("Query: %q\n", q)
    52 	//log.Printf("Query: %q\n", q)
    48 	log.Println("Starting handshake...")
    53 	log.Println("Starting handshake...")
    49 	n, err := s.Write(q)
    54 	n, err := s.Write(q)
    50 	if err != nil {
    55 	if err != nil {
    51 		log.Fatal(err)
    56 		return items, err
    52 		return
       
    53 	}
    57 	}
    54 
    58 
    55 	buf := make([]byte, 128)
    59 	buf := make([]byte, 128)
    56 	n, err = getData(s, buf, 1)
    60 	n, err = getData(s, buf, 1)
    57 	if err != nil {
    61 	if err != nil {
    58 		log.Fatal(err)
    62 		return items, err
    59 		return
       
    60 	}
    63 	}
    61 	if n == 1 && buf[0] == '\x55' {
    64 	if n == 1 && buf[0] == '\x55' {
    62 		log.Println("Handshake successful.")
    65 		log.Println("Handshake successful.")
    63 	} else {
    66 	} else {
    64 		log.Printf("(%d bytes) %q\n", n, buf[:n])
    67 		log.Printf("(%d bytes) %q\n", n, buf[:n])
    65 		s.Close()
    68 		s.Close()
    66 		return
    69 		return items, fmt.Errorf("handshake failed")
    67 	}
    70 	}
    68 
    71 
    69 	// =================== Desc =====================
    72 	// =================== Desc =====================
    70 	q = []byte("\xa4")
    73 	q = []byte("\xa4")
    71 	//log.Printf("Query: %q\n", q)
    74 	//log.Printf("Query: %q\n", q)
    72 	log.Println("Requesting device description...")
    75 	log.Println("Requesting device description...")
    73 	n, err = s.Write(q)
    76 	n, err = s.Write(q)
    74 	if err != nil {
    77 	if err != nil {
    75 		log.Fatal(err)
    78 		return items, err
    76 		return
       
    77 	}
    79 	}
    78 
    80 
    79 	n, err = getData(s, buf, 32)
    81 	n, err = getData(s, buf, 32)
    80 	log.Printf("DESC> %q\n", buf[:n])
    82 	log.Printf("DESC> %q\n", buf[:n])
    81 
    83 
    83 	q = []byte("\xa2")
    85 	q = []byte("\xa2")
    84 	//log.Printf("Query: %q\n", q)
    86 	//log.Printf("Query: %q\n", q)
    85 	log.Println("Requesting data counter...")
    87 	log.Println("Requesting data counter...")
    86 	n, err = s.Write(q)
    88 	n, err = s.Write(q)
    87 	if err != nil {
    89 	if err != nil {
    88 		log.Fatal(err)
    90 		return items, err
    89 		return
       
    90 	}
    91 	}
    91 
    92 
    92 	n, err = getData(s, buf, 1)
    93 	n, err = getData(s, buf, 1)
    93 	if err != nil {
    94 	if err != nil {
    94 		log.Fatal(err)
    95 		return items, err
    95 		return
       
    96 	}
    96 	}
    97 	var nRecords int
    97 	var nRecords int
    98 	if n == 1 {
    98 	if n == 1 {
    99 		log.Printf("%d item(s) available.", buf[0])
    99 		log.Printf("%d item(s) available.", buf[0])
   100 		nRecords = int(buf[0])
   100 		nRecords = int(buf[0])
   101 	} else {
   101 	} else {
   102 		log.Printf("(%d bytes) %q\n", n, buf[:n])
   102 		log.Printf("(%d bytes) %q\n", n, buf[:n])
   103 		return
   103 		return items, fmt.Errorf("no measurement found")
   104 	}
   104 	}
   105 
   105 
       
   106 	// =================== Records =====================
   106 	for i := 0; i < nRecords; i++ {
   107 	for i := 0; i < nRecords; i++ {
   107 		q = []byte{'\xa3', uint8(i + 1)}
   108 		q = []byte{'\xa3', uint8(i + 1)}
   108 		//log.Printf("Query: %q\n", q)
   109 		//log.Printf("Query: %q\n", q)
   109 		//log.Printf("Requesting measurement %d...", i+1)
   110 		//log.Printf("Requesting measurement %d...", i+1)
   110 		n, err = s.Write(q)
   111 		n, err = s.Write(q)
   111 		if err != nil {
   112 		if err != nil {
   112 			log.Fatal(err)
   113 			return items, err
   113 			return
       
   114 		}
   114 		}
   115 
   115 
   116 		n, err = getData(s, buf, 9)
   116 		n, err = getData(s, buf, 9)
   117 		//log.Printf("DESC> %q\n", buf[:n])
   117 		//log.Printf("DESC> %q\n", buf[:n])
   118 
   118 
   119 		var data measurement
   119 		var data measurement
   120 		data.header = int(buf[0])
   120 		data.Header = int(buf[0])
   121 		data.systolic = int(buf[1]) + 25
   121 		data.Systolic = int(buf[1]) + 25
   122 		data.diastolic = int(buf[2]) + 25
   122 		data.Diastolic = int(buf[2]) + 25
   123 		data.pulse = int(buf[3])
   123 		data.Pulse = int(buf[3])
   124 		data.month = int(buf[4])
   124 		data.Month = int(buf[4])
   125 		data.day = int(buf[5])
   125 		data.Day = int(buf[5])
   126 		data.hour = int(buf[6])
   126 		data.Hour = int(buf[6])
   127 		data.minute = int(buf[7])
   127 		data.Minute = int(buf[7])
   128 		data.year = int(buf[8]) + 2000
   128 		data.Year = int(buf[8]) + 2000
   129 		fmt.Printf("%d;%x;%d-%02d-%02d %02d:%02d;%d;%d;%d\n",
   129 		items = append(items, data)
   130 			i+1, data.header,
       
   131 			data.year, data.month, data.day,
       
   132 			data.hour, data.minute,
       
   133 			data.systolic, data.diastolic, data.pulse)
       
   134 	}
   130 	}
   135 
   131 
   136 	s.Close()
   132 	s.Close()
   137 }
   133 	return items, nil
       
   134 }
       
   135 
       
   136 func loadFromJSONFile(filename string) (items []measurement, err error) {
       
   137 	data, err := ioutil.ReadFile(filename)
       
   138 	if err != nil {
       
   139 		return items, err
       
   140 	}
       
   141 
       
   142 	err = json.Unmarshal(data, &items)
       
   143 	return items, err
       
   144 }
       
   145 
       
   146 func mergeItems(newItems, oldItems []measurement) []measurement {
       
   147 	var result []measurement
       
   148 	var j int
       
   149 	// TODO: Would be better to compare dates and merge chronologically...
       
   150 	for _, nItem := range newItems {
       
   151 		result = append(result, nItem)
       
   152 		if j+1 <= len(oldItems) && nItem == oldItems[j] {
       
   153 			j++
       
   154 		}
       
   155 	}
       
   156 	if j+1 <= len(oldItems) {
       
   157 		result = append(result, oldItems[j:]...)
       
   158 	}
       
   159 	return result
       
   160 }
       
   161 
       
   162 func main() {
       
   163 	inFile := flag.String([]string{"-input-file", "i"}, "", "Input JSON file")
       
   164 	outFile := flag.String([]string{"-output-file", "o"}, "", "Output JSON file")
       
   165 	limit := flag.Uint([]string{"-limit", "l"}, 0, "Limit number of items")
       
   166 	format := flag.String([]string{"-format", "f"}, "", "Output format (csv, json)")
       
   167 	avg := flag.Bool([]string{"-average", "a"}, false, "Compute average")
       
   168 	merge := flag.Bool([]string{"-merge", "m"}, false,
       
   169 		"Try to merge input JSON file with fetched data")
       
   170 	device := flag.String([]string{"-device", "d"}, "/dev/ttyUSB0", "Serial device")
       
   171 
       
   172 	flag.Parse()
       
   173 
       
   174 	switch *format {
       
   175 	case "":
       
   176 		if *outFile == "" {
       
   177 			*format = "csv"
       
   178 		}
       
   179 		break
       
   180 	case "json", "csv":
       
   181 		break
       
   182 	default:
       
   183 		log.Fatal("Unknown output format.  Possible choices are csv, json.")
       
   184 	}
       
   185 
       
   186 	var err error
       
   187 	var items []measurement
       
   188 
       
   189 	if *inFile == "" {
       
   190 		// Read from device
       
   191 		if items, err = fetchData(*device); err != nil {
       
   192 			log.Fatal(err)
       
   193 		}
       
   194 	} else {
       
   195 		// Read from file
       
   196 		var fileItems []measurement
       
   197 		if fileItems, err = loadFromJSONFile(*inFile); err != nil {
       
   198 			log.Fatal(err)
       
   199 		}
       
   200 		if *merge {
       
   201 			if items, err = fetchData(*device); err != nil {
       
   202 				log.Fatal(err)
       
   203 			}
       
   204 			items = mergeItems(items, fileItems)
       
   205 		} else {
       
   206 			items = fileItems
       
   207 		}
       
   208 	}
       
   209 
       
   210 	if *limit > 0 && len(items) > int(*limit) {
       
   211 		items = items[0:*limit]
       
   212 	}
       
   213 
       
   214 	var avgMeasure measurement
       
   215 	var avgCount int
       
   216 
       
   217 	for i, data := range items {
       
   218 		if *format == "csv" {
       
   219 			fmt.Printf("%d;%x;%d-%02d-%02d %02d:%02d;%d;%d;%d\n",
       
   220 				i+1, data.Header,
       
   221 				data.Year, data.Month, data.Day,
       
   222 				data.Hour, data.Minute,
       
   223 				data.Systolic, data.Diastolic, data.Pulse)
       
   224 		}
       
   225 
       
   226 		avgMeasure.Systolic += data.Systolic
       
   227 		avgMeasure.Diastolic += data.Diastolic
       
   228 		avgMeasure.Pulse += data.Pulse
       
   229 		avgCount++
       
   230 	}
       
   231 
       
   232 	if *avg && avgCount > 0 {
       
   233 		avgMeasure.Systolic /= avgCount
       
   234 		avgMeasure.Diastolic /= avgCount
       
   235 		avgMeasure.Pulse /= avgCount
       
   236 
       
   237 		fmt.Printf("Average: %d;%d;%d\n", avgMeasure.Systolic,
       
   238 			avgMeasure.Diastolic, avgMeasure.Pulse)
       
   239 	}
       
   240 
       
   241 	if *format == "json" || *outFile != "" {
       
   242 		rawJSON, err := json.MarshalIndent(items, "", "  ")
       
   243 		if err != nil {
       
   244 			log.Fatal("Error:", err)
       
   245 		}
       
   246 
       
   247 		if *format == "json" {
       
   248 			fmt.Println(string(rawJSON))
       
   249 		}
       
   250 		if *outFile != "" {
       
   251 			err = ioutil.WriteFile(*outFile, rawJSON, 0600)
       
   252 			if err != nil {
       
   253 				log.Println("Could not write output file:", err)
       
   254 			}
       
   255 		}
       
   256 	}
       
   257 }