func (resp *response) IsCorrect() error {
	var checkSum byte
	for i := 0; i < 6; i++ {
		checkSum += resp.Data[i]
	}
	if checkSum != resp.CheckSum {
		return fmt.Errorf("bad checksum: %#v", resp)
	}
	return nil
}
IsCorrect returns nil if the responses checksum matches, an error
otherwise.
package sds011
import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"time"
	log "github.com/golang/glog"
	"github.com/jacobsa/go-serial/serial"
)
type command byte
type mode byte
const (
	commandReportMode command = 2
	commandQuery      command = 4
	commandDeviceID   command = 5
	commandWorkState  command = 6
	commandFirmware   command = 7
	commandCycle      command = 8
	modeGet mode = 0
	modeSet mode = 1
	reportModeActive byte = 0
	reportModeQuery  byte = 1
	workStateSleeping  byte = 0
	workStateMeasuring byte = 1
)
type response struct {
	Header   byte  
	Command  byte  
	Data     [6]byte
	CheckSum byte
	Tail     byte  
}
func (resp *response) IsReply() bool {
	return resp.Command == 0xC5
}
func (resp *response) PM25() float64 {
	if resp.IsReply() {
		panic(fmt.Sprintf("access to field that doesn't work with this type of response %#v", resp))
	}
	return float64(binary.LittleEndian.Uint16(resp.Data[0:2])) / 10.0
}
func (resp *response) PM10() float64 {
	if resp.IsReply() {
		panic(fmt.Sprintf("access to field that doesn't work with this type of response %#v", resp))
	}
	return float64(binary.LittleEndian.Uint16(resp.Data[2:4])) / 10.0
}
func (resp *response) checkMatches(cmd command) {
	if resp.Data[0] != byte(cmd) {
		panic(fmt.Sprintf("access to field that doesn't work with this type of response %#v", resp))
	}
}
func (resp *response) ID() uint16 {
	if resp.IsReply() {
		panic(fmt.Sprintf("access to field that doesn't work with this type of response %#v", resp))
	}
	return binary.LittleEndian.Uint16(resp.Data[4:6])
}
func (resp *response) Firmware() string {
	resp.checkMatches(commandFirmware)
	return fmt.Sprintf("%02d-%02d-%02d", resp.Data[1], resp.Data[2], resp.Data[3])
}
func (resp *response) DeviceID() string {
	resp.checkMatches(commandDeviceID)
	return fmt.Sprintf("%02d%02d", resp.Data[1], resp.Data[2])
}
func (resp *response) ReportMode() byte {
	resp.checkMatches(commandReportMode)
	return resp.Data[2]
}
func (resp *response) Cycle() uint8 {
	resp.checkMatches(commandCycle)
	return resp.Data[2]
}
func (resp *response) WorkState() byte {
	resp.checkMatches(commandWorkState)
	return resp.Data[2]
}
type request struct {
	Header     byte      
	SendMarker byte      
	Command    byte      
	Mode       byte      
	Data       [11]byte  
	DeviceID   [2]byte   
	CheckSum   byte      
	Tail       byte      
}
func makeRequest(cmd command, mod mode, value byte) *request {
	data := [11]byte{}
	data[0] = value
	req := &request{
		Header:     0xAA,
		SendMarker: 0xB4,
		Command:    byte(cmd),
		Mode:       byte(mod),
		Data:       data,
		DeviceID:   [2]byte{0xFF, 0xFF},
		Tail:       0xAB,
	}
	checksum := int(req.Command) + int(req.Mode)
	for _, v := range data {
		checksum += int(v)
	}
	for _, v := range req.DeviceID {
		checksum += int(v)
	}
	req.CheckSum = byte(checksum % 256)
	return req
}