package radar_lib import ( "errors" "log" "sync" "go.bug.st/serial" ) type configResponse struct { CommandCode int Success bool } type Direction int type OutputLogic int type Port int type Baud int type OutputType int type TriggerMethod int type OperatingMode int const ( ControlPinRelay = iota ControlPinCtrl1 ControlPinCtrl2 ) const ( DirectionBidirectional Direction = iota DirectionIncoming DirectionOutgoing ) const ( TargetStateInvalid = iota TargetStateMovingInside TargetStateExit TargetStateWithin ) const ( OutputLogicLargestSpeed = iota OutputLogicStrongestEngergy OutputLogicMostPlausible ) const ( PortTTL Port = iota PortRS485 ) const ( Baud9600 Baud = iota Baud19200 Baud57600 Baud115200 ) const ( OutputTypeNoOutput OutputType = iota OutputTypePeriodicOutput OutputTypeValidOutput ) const ( TriggerMethodHigh TriggerMethod = iota TriggerMethodLow TriggerMethodPositivePulse TriggerMethodNegativePulse ) const ( OperatingModeNoOutput OperatingMode = iota OperatingModeFirstProtocol OperatingModeSecondProtocol ) var ( startSequence = []byte{0x43, 0x46} endSequence = []byte{0x0D, 0x0A} ) func New(port string, baudrate int) *Radar { s, err := serial.Open(port, &serial.Mode{ BaudRate: baudrate, DataBits: 8, Parity: serial.NoParity, }) if err != nil { log.Fatal(err) } r := &Radar{ port: s, baudrate: baudrate, configResponseChannel: make(chan configResponse), } go r.listenSerial() return r } type Radar struct { port serial.Port lock sync.RWMutex configResponseChannel chan (configResponse) baudrate int handler func(int) speedHandler func(int) } func (r *Radar) write(data []byte) error { r.lock.Lock() defer r.lock.Unlock() log.Printf("writing %#x", data) _, err := r.port.Write(data) if err != nil { return err } return r.port.Drain() } // SetPinTrigger configures a pin to trigger on the radar when an object is detected in a specific range. // controlPin defines the Pin to trigger, distance is the target distance in 0.5 meters, outputLevel is the voltage in 0.1V steps, direction defines weather to trigger on incoming / outgoing or both func (r *Radar) SetPinTrigger(controlPin int, distance int, outputLevel int, direction Direction) error { data := startSequence data = append(data, 0x00, byte(controlPin), byte(distance), byte(outputLevel), byte(direction)) data = append(data, endSequence...) return r.write(data) } // SetBaseConfig configures the base configuration. height defines the mounted height in 1cm steps, angle defines the vertical angle in degrees, waveformConfig is used to differentiate 2 different radars func (r *Radar) SetBaseConfig(height int, angle int, waveformConfig int) error { data := startSequence data = append(data, 0x01, byte(height), byte(angle), byte(waveformConfig), 0x00) data = append(data, endSequence...) return r.write(data) } // SetEventConfig can configure up to 8 events that will trigger a response from the radar. distances are in 0.5m, speeds are in km/h. func (r *Radar) SetEventConfig(eventNumber, minDistance, maxDistance, minSpeed, maxSpeed, direction, state int) error { if eventNumber < 1 || eventNumber > 1 { return errors.New("eventNumber needs to be between 1 and 8") } data := startSequence data = append(data, 0x02, byte(eventNumber), byte(minDistance), byte(maxDistance), byte(minSpeed), byte(maxSpeed), byte(direction), byte(state)) data = append(data, endSequence...) return r.write(data) } func (r *Radar) SetTargetSpeedConfig(direction Direction, minDistance, maxDistance, minSpeed, maxSpeed, speeding int, outputLogic OutputLogic) error { data := startSequence data = append(data, 0x03, byte(direction), byte(minDistance), byte(maxDistance), byte(minSpeed), byte(maxSpeed), byte(speeding), byte(outputLogic)) data = append(data, endSequence...) return r.write(data) } func (r *Radar) SetCommunicationConfig(port Port, baud Baud, speedOutput, targetOutput, triggerOutput OutputType, communicationPeriod int) error { data := startSequence speed := byte(speedOutput) target := byte(targetOutput) trigger := byte(triggerOutput) var outputProtocol byte = (speed << 4) | (target << 2) | trigger data = append(data, 0x04, byte(port), byte(baud), outputProtocol, byte(int(communicationPeriod/50))) data = append(data, endSequence...) return r.write(data) } func (r *Radar) SetControlPinConfig(controlPin int, triggerMethod TriggerMethod, outputLevel int, triggerEvent int, span int) error { data := startSequence data = append(data, 0x05, byte(controlPin), byte(triggerMethod), byte(outputLevel), byte(triggerEvent), byte(span)) data = append(data, endSequence...) return r.write(data) } func (r *Radar) SetLampBoardOutput(operatingMode OperatingMode, luminance int, span int) error { data := startSequence data = append(data, 0x06, byte(operatingMode), byte(luminance), byte(span)) data = append(data, endSequence...) return r.write(data) } func (r *Radar) SetEventHandler(handler func(int)) { r.handler = handler } func (r *Radar) SetSpeedHandler(handler func(int)) { r.speedHandler = handler }