Reorg, Update Tests and Github Actions (#2)

* Reorg, Update Tests and Github Actions

* Install libusb and only test on ubuntu
This commit is contained in:
Justin Hammond 2021-09-23 00:59:07 +08:00 committed by GitHub
parent 334ea05709
commit 49bc92fa8d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 682 additions and 467 deletions

View file

@ -1,4 +1,12 @@
on: [ push, pull_request ] on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
# Goreadme needs permissions to update pull requests comments and change contents.
pull-requests: write
contents: write
name: Build name: Build
jobs: jobs:
test: test:
@ -13,14 +21,13 @@ jobs:
uses: actions/setup-go@v1 uses: actions/setup-go@v1
with: with:
go-version: ${{ matrix.go-version }} go-version: ${{ matrix.go-version }}
- name: Install libusb-1.0-0-dev
run: sudo apt-get install libusb-1.0-0-dev
- name: Checkout code - name: Checkout code
uses: actions/checkout@v1 uses: actions/checkout@v1
- name: Install libusb-1.0-0-dev
run: sudo apt-get install libusb-1.0-0-dev
- name: Run tests - name: Run tests
run: go test -v -race run: go test -v -race ./...
codecov:
coverage:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: test needs: test
steps: steps:
@ -29,11 +36,38 @@ jobs:
uses: actions/setup-go@v1 uses: actions/setup-go@v1
with: with:
go-version: 1.16.x go-version: 1.16.x
- name: Install libusb-1.0-0-dev
run: sudo apt-get install libusb-1.0-0-dev
- name: Checkout code - name: Checkout code
uses: actions/checkout@v1 uses: actions/checkout@v1
- name: Install libusb-1.0-0-dev
run: sudo apt-get install libusb-1.0-0-dev
- name: Run tests - name: Run tests
run: go test -v -race -covermode=atomic -coverprofile=coverage.txt run: go test -v -race -covermode=atomic -coverprofile=coverage.out ./...
- name: Upload coverage to Codecov - name: CodeCov
run: bash <(curl -s https://codecov.io/bash) uses: codecov/codecov-action@v2
lint:
name: Lint project using GolangCI Lint
runs-on: ubuntu-latest
needs: test
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v1
- name: GolangCI-Lint Action
uses: golangci/golangci-lint-action@v2.5.2
with:
version: latest
only-new-issues: true
args: --issues-exit-code=0
goreadme:
runs-on: ubuntu-latest
needs: [codecov, lint]
steps:
- name: Check out repository
uses: actions/checkout@v2
- name: Update readme according to Go doc
uses: posener/goreadme@v1
with:
badge-codecov: 'true'
badge-godoc: 'true'
email: 'justin@dynam.ac'
title: 'Go-DCDCUSB'
github-token: '${{ secrets.GITHUB_TOKEN }}'

View file

@ -1,16 +0,0 @@
on: [ push, pull_request ]
name: Linter
jobs:
lint:
name: Lint project using GolangCI Lint
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v1
- name: GolangCI-Lint Action
uses: golangci/golangci-lint-action@v2.5.2
with:
version: latest
only-new-issues: true
args: --issues-exit-code=0

View file

@ -1,42 +1,42 @@
// Copyright 2013 Google Inc. All rights reserved. /*
// Copyright 2016 the gousb Authors. All rights reserved. MIT License
//
// Licensed under the Apache License, Version 2.0 (the "License"); Copyright (c) 2021 Justin Hammond
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// http://www.apache.org/licenses/LICENSE-2.0 in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// Unless required by applicable law or agreed to in writing, software copies of the Software, and to permit persons to whom the Software is
// distributed under the License is distributed on an "AS IS" BASIS, furnished to do so, subject to the following conditions:
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and The above copyright notice and this permission notice shall be included in all
// limitations under the License. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// lsusb lists attached USB devices.
package main package main
import ( import (
"context" "context"
"flag"
"fmt"
"log" "log"
"time" "time"
"github.com/Fishwaldo/go-dcdc200" "github.com/Fishwaldo/go-dcdc200"
"github.com/google/gousb"
"github.com/google/gousb/usbid"
) )
var (
debug = flag.Int("debug", 0, "libusb debug level (0..3)")
)
func main() { func main() {
test() dc := dcdcusb.DcDcUSB{}
dc.Init()
dc := dcdc200.Dcdc200{} if ok, err := dc.Scan(); !ok {
if ok, err := dc.Scan(); ok != true {
log.Fatalf("Scan Failed: %v", err) log.Fatalf("Scan Failed: %v", err)
return return
} }
@ -49,64 +49,3 @@ func main() {
} }
dc.Close() dc.Close()
} }
func test() {
flag.Parse()
// Only one context should be needed for an application. It should always be closed.
ctx := gousb.NewContext()
defer ctx.Close()
// Debugging can be turned on; this shows some of the inner workings of the libusb package.
ctx.Debug(*debug)
// OpenDevices is used to find the devices to open.
devs, err := ctx.OpenDevices(func(desc *gousb.DeviceDesc) bool {
// The usbid package can be used to print out human readable information.
fmt.Printf("%03d.%03d %s:%s %s\n", desc.Bus, desc.Address, desc.Vendor, desc.Product, usbid.Describe(desc))
fmt.Printf(" Protocol: %s\n", usbid.Classify(desc))
// The configurations can be examined from the DeviceDesc, though they can only
// be set once the device is opened. All configuration references must be closed,
// to free up the memory in libusb.
for _, cfg := range desc.Configs {
// This loop just uses more of the built-in and usbid pretty printing to list
// the USB devices.
fmt.Printf(" %s:\n", cfg)
for _, intf := range cfg.Interfaces {
fmt.Printf(" --------------\n")
for _, ifSetting := range intf.AltSettings {
fmt.Printf(" %s\n", ifSetting)
fmt.Printf(" %s\n", usbid.Classify(ifSetting))
for _, end := range ifSetting.Endpoints {
fmt.Printf(" %s\n", end)
}
}
}
fmt.Printf(" --------------\n")
}
// After inspecting the descriptor, return true or false depending on whether
// the device is "interesting" or not. Any descriptor for which true is returned
// opens a Device which is retuned in a slice (and must be subsequently closed).
return false
})
// All Devices returned from OpenDevices must be closed.
defer func() {
for _, d := range devs {
d.Close()
}
}()
// OpenDevices can occasionally fail, so be sure to check its return value.
if err != nil {
log.Fatalf("list: %s", err)
}
for _, dev := range devs {
// Once the device has been selected from OpenDevices, it is opened
// and can be interacted with.
_ = dev
}
}

6
codecov.yml Normal file
View file

@ -0,0 +1,6 @@
coverage:
status:
project:
default:
target: auto
threshold: 10%

View file

@ -1,6 +1,6 @@
// Code generated by "stringer -type=DcdcModet"; DO NOT EDIT. // Code generated by "stringer -type=DcdcModet"; DO NOT EDIT.
package dcdc200 package dcdcusb
import "strconv" import "strconv"

View file

@ -1,6 +1,6 @@
// Code generated by "stringer -type=DcdcStatet"; DO NOT EDIT. // Code generated by "stringer -type=DcdcStatet"; DO NOT EDIT.
package dcdc200 package dcdcusb
import "strconv" import "strconv"

357
dcdcusb.go Executable file
View file

@ -0,0 +1,357 @@
/*
MIT License
Copyright (c) 2021 Justin Hammond
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package dcdcusb
import (
"context"
"errors"
"fmt"
"sync"
"time"
"github.com/Fishwaldo/go-logadapter"
"github.com/Fishwaldo/go-logadapter/loggers/std"
"github.com/google/gousb"
)
// Main Structure for the DCDCUSB Communications
type DcDcUSB struct {
ctx *gousb.Context
dev *gousb.Device
intf *gousb.Interface
done func()
log logadapter.Logger
initOnce sync.Once
}
// Represents the Settings for Off and Hardoff Delays when power is lost
type TimerConfigt struct {
// After Ignition Lost, this the time waiting till we toggle the Power Switch I/F
OffDelay time.Duration `json:"off_delay,omitempty"`
// After the Power Switch I/F is toggled, this is the delay before we cut power
HardOff time.Duration `json:"hard_off,omitempty"`
}
// Status of Various Peripherals
type Peripheralst struct {
// ??
OutSwVin bool `json:"out_sw_vin,omitempty"`
// ??
OutPsw bool `json:"out_psw,omitempty"`
// ??
OutStartOutput bool `json:"out_start_output,omitempty"`
// Status of the Onboard Led
OutLed bool `json:"out_led,omitempty"`
// If the VOut is within range.
InVoutGood bool `json:"in_vout_good,omitempty"`
}
// Overall Status of the DCDCUSB Power Supply
type Params struct {
// What the Vout Setting is configured for
VoutSet float32 `json:"vout_set,omitempty"`
// What Voltage the Config Jumpers are set for VOut
VoutConfig float32 `json:"vout_config,omitempty"`
// The Input Voltage
Vin float32 `json:"vin,omitempty"`
// The Ignition Voltage
Vign float32 `json:"vign,omitempty"`
// What the Actual VOut Voltage is
VoutActual float32 `json:"vout_actual,omitempty"`
// Status of Various Peripherals
Peripherals Peripheralst `json:"peripherals,omitempty"`
// ?? (Not Output Enabled?)
Output bool `json:"output,omitempty"`
// ??
AuxVIn bool `json:"aux_v_in,omitempty"`
// Firmware Version?
Version string `json:"version,omitempty"`
// State of the Power Supply
State DcdcStatet `json:"state,omitempty"`
// Config Registers (unknown)
CfgRegisters byte `json:"cfg_registers,omitempty"`
// Voltage Flags (Unknown)
VoltFlags byte `json:"volt_flags,omitempty"`
// Timer Flags (Unknown)
TimerFlags byte `json:"timer_flags,omitempty"`
// The configured countdown times for the Timer upon Power Loss
TimerConfig TimerConfigt `json:"timer_config,omitempty"`
// Current Power Loss Debounce Timer
TimerWait time.Duration `json:"timer_wait,omitempty"`
// Current VOut Countdown Timer
TimerVOut time.Duration `json:"timer_v_out,omitempty"`
// Current VAux Countdown timer
TimerVAux time.Duration `json:"timer_v_aux,omitempty"`
// Current Power Switch Toggle Count Down Timer
TimerPRWSW time.Duration `json:"timer_prwsw,omitempty"`
// Current Soft Off Countdown Timer
TimerSoftOff time.Duration `json:"timer_soft_off,omitempty"`
// Current Hard Off Countdown Timer
TimerHardOff time.Duration `json:"timer_hard_off,omitempty"`
// Current Script Position
ScriptPointer byte `json:"script_pointer,omitempty"`
// Current Operating Mode
Mode DcdcModet `json:"mode,omitempty"`
}
// Initialize the DCDCUSB Communications. Should be first function called before any other methods are called
func (dc *DcDcUSB) Init() {
dc.initOnce.Do(func() {
if dc.log == nil {
templogger := stdlogger.DefaultLogger()
templogger.Log.SetPrefix("DCDCUSB")
dc.log = templogger
}
})
dc.ctx = gousb.NewContext()
}
// Set a Custom Logger based on https://github.com/Fishwaldo/go-logadapter
// If not set, then the Library will use the Std Library Logger
func (dc *DcDcUSB) SetLogger(log logadapter.Logger) {
dc.log = log
}
// Set the debug level for the GoUSB Library
func (dc *DcDcUSB) SetUSBDebug(level int) {
if dc.ctx != nil {
dc.ctx.Debug(level)
}
}
// Scan for a DCDCUSB connection, returns true if found, or false (and optional error) if there
// was a failure setting up communications with it.
func (dc *DcDcUSB) Scan() (bool, error) {
var err error
dc.dev, err = dc.ctx.OpenDeviceWithVIDPID(dcdc200_vid, dcdc200_pid)
if err != nil {
dc.log.Warn("Could Not Open Device: %v", err)
dc.Close()
return false, err
}
if dc.dev == nil {
dc.log.Warn("Can't Find Device")
dc.Close()
return false, nil
}
err = dc.dev.SetAutoDetach(true)
if err != nil {
dc.log.Error("%s.SetAutoDetach(true): %v", dc.dev, err)
}
confignum, _ := dc.dev.ActiveConfigNum()
dc.log.Trace("Device Config: %s %d", dc.dev.String(), confignum)
// desc, _ := dc.dev.GetStringDescriptor(1)
// manu, _ := dc.dev.Manufacturer()
// prod, _ := dc.dev.Product()
// serial, _ := dc.dev.SerialNumber()
dc.intf, dc.done, err = dc.dev.DefaultInterface()
if err != nil {
dc.log.Error("%s.Interface(): %v", dc.dev, err)
dc.Close()
return false, err
}
dc.log.Trace("Interface: %s", dc.intf.String())
dc.log = dc.log.With("Device", dc.intf.String())
return true, nil
}
func (dc *DcDcUSB) Close() {
if dc.intf != nil {
dc.done()
dc.intf.Close()
}
if dc.dev != nil {
dc.dev.Close()
}
if dc.ctx != nil {
dc.ctx.Close()
}
}
// Gets All current Params from the DCDCUSB power Supply.
// Set a Timeout/Deadline Context to cancel slow calls
func (dc *DcDcUSB) GetAllParam(ctx context.Context) {
if dc.intf == nil {
dc.log.Warn("Interface Not Opened")
return
}
outp, err := dc.intf.OutEndpoint(0x01)
if err != nil {
dc.log.Warn("Can't Get OutPoint: %s", err)
return
}
//log.Printf("OutEndpoint: %v", outp)
var send = make([]byte, 24)
send[0] = cmdGetAllValues
//send = append(send, 0)
//log.Printf("About to Send %v", send)
len, err := outp.WriteContext(ctx, send)
if err != nil {
dc.log.Warn("Cant Send GetAllValues Command: %s (%v) - %d", err, send, len)
return
}
//log.Printf("Sent %d Bytes", len)
inp, err := dc.intf.InEndpoint(0x81)
if err != nil {
dc.log.Warn("Can't Get OutPoint: %s", err)
return
}
//log.Printf("InEndpoint: %v", inp)
var recv = make([]byte, 24)
len, err = inp.ReadContext(ctx, recv)
if err != nil {
dc.log.Warn("Can't Read GetAllValues Command: %s", err)
return
}
//log.Printf("Got %d Bytes", len)
dc.log.Trace("Got %v", recv)
dc.parseAllValues(recv, len)
}
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
//ignition connect: 2021/09/20 15:51:38 Got [130 133 7 76 75 43 27 133 215 251 1 0 0 0 0 0 0 0 0 3 68 0 0 167]
//ignition connect2 2021/09/20 15:52:14 Got [130 133 7 76 75 44 27 133 215 251 1 0 0 0 0 0 0 0 0 3 32 0 0 167]
//ignition disconnect: 2021/09/20 15:50:39 Got [130 133 8 76 0 43 27 133 205 251 1 0 0 0 0 0 0 0 0 3 127 0 0 167]
// 2021/09/20 16:12:54 Got [130 133 8 76 0 44 25 133 205 251 1 0 0 0 0 0 0 0 0 0 0 0 0 167]
// 2021/09/20 16:12:56 Got [130 133 16 76 0 44 27 133 205 247 1 0 0 0 0 0 0 0 0 0 0 0 59 167]
// 2021/09/20 16:13:54 Got [130 133 16 76 0 44 9 133 205 247 1 0 0 0 0 0 0 0 0 0 0 0 0 167]
func (dc *DcDcUSB) parseAllValues(buf []byte, len int) (Params, error) {
switch buf[0] {
case cmdRecvAllValues:
param := Params{}
param.Mode = dc.modeToConst((buf[1] >> 6) & 0x7)
param.VoutConfig = dc.voutConfigtoFloat((buf[1] >> 2) & 0x07)
param.TimerConfig = dc.timerConfigToDuration(buf[1] & 0x03)
param.State = dc.stateToConst(buf[2])
param.Vin = float32(buf[3]) * float32(0.1558)
param.Vign = float32(buf[4]) * float32(0.1558)
param.VoutActual = float32(buf[5]) * float32(0.1170)
param.Peripherals = dc.peripheralsState(buf[6])
param.CfgRegisters = buf[7]
param.VoltFlags = buf[8]
param.TimerFlags = buf[9]
param.ScriptPointer = buf[10]
param.Version = fmt.Sprintf("%d.%d", int((buf[23]>>5)&0x07), int(buf[23])&0x1F)
param.TimerWait = dc.convertTime(buf[11:13])
param.TimerVOut = dc.convertTime(buf[13:15])
param.TimerVAux = dc.convertTime(buf[15:17])
param.TimerPRWSW = dc.convertTime(buf[17:19])
param.TimerSoftOff = dc.convertTime(buf[19:21])
param.TimerHardOff = dc.convertTime(buf[21:23])
dc.log.Trace("DCDC Params: %+v\n", param)
return param, nil
}
return Params{}, errors.New("unknown command recieved")
}
func (dc *DcDcUSB) modeToConst(mode byte) DcdcModet {
switch mode {
case 0:
return Dumb
case 1:
return Script
case 2:
return Automotive
case 3:
return UPS
default:
return Unknown
}
}
func (dc *DcDcUSB) voutConfigtoFloat(config byte) float32 {
switch config {
case 0:
return float32(12.0)
case 1:
return float32(5.0)
case 2:
return float32(6.0)
case 3:
return float32(9.0)
case 4:
return float32(13.5)
case 5:
return float32(16.0)
case 6:
return float32(19.0)
case 7:
return float32(24.0)
default:
return float32(-1)
}
}
func (dc DcDcUSB) timerConfigToDuration(config byte) TimerConfigt {
switch config {
case 0:
return TimerConfigt{OffDelay: 0, HardOff: 0}
case 1:
return TimerConfigt{OffDelay: 15 * time.Minute, HardOff: 1 * time.Minute}
case 2:
return TimerConfigt{OffDelay: 5 * time.Second, HardOff: -1}
case 3:
return TimerConfigt{OffDelay: 30 * time.Minute, HardOff: 1 * time.Minute}
case 4:
return TimerConfigt{OffDelay: 5 * time.Second, HardOff: 1 * time.Minute}
case 5:
return TimerConfigt{OffDelay: 15 * time.Minute, HardOff: -1}
case 6:
return TimerConfigt{OffDelay: 1 * time.Minute, HardOff: 1 * time.Minute}
case 7:
return TimerConfigt{OffDelay: 1 * time.Hour, HardOff: -1}
default:
return TimerConfigt{OffDelay: -1, HardOff: -1}
}
}
func (dc DcDcUSB) stateToConst(state byte) DcdcStatet {
switch state {
case 7:
return StateOk
case 8:
return StateIgnOff
case 16:
return StateHardOffCountdown
default:
return StateUnknown
}
}
func (dc DcDcUSB) peripheralsState(state byte) Peripheralst {
p := Peripheralst{
InVoutGood: ((state & 0x01) != 0),
OutLed: ((state & 0x02) != 0),
OutPsw: ((state & 0x04) != 0),
OutStartOutput: ((state & 0x08) != 0),
OutSwVin: ((state & 0x10) != 0),
}
return p
}
func (dc DcDcUSB) convertTime(raw []byte) time.Duration {
duration := int64(raw[0]) << 8
duration += int64(raw[1])
return time.Duration(duration * int64(time.Second))
}

View file

@ -1,4 +1,28 @@
package dcdc200 /*
MIT License
Copyright (c) 2021 Justin Hammond
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package dcdcusb
import ( import (
"testing" "testing"
@ -7,12 +31,13 @@ import (
func TestParseAllValues(t *testing.T) { func TestParseAllValues(t *testing.T) {
var test1 = []byte{130, 133, 7, 76, 75, 43, 27, 133, 215, 251, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 68, 0, 0, 167} var test1 = []byte{130, 133, 7, 76, 75, 43, 27, 133, 215, 251, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 68, 0, 0, 167}
dc := Dcdc200{} dc := DcDcUSB{}
dc.Init()
result, err := dc.parseAllValues(test1, 24) result, err := dc.parseAllValues(test1, 24)
if err != nil { if err != nil {
t.Fatalf("Error Returned from parseAllValues: %v", err) t.Fatalf("Error Returned from parseAllValues: %v", err)
} }
t.Logf("Param %+v", result) // t.Logf("Param %+v", result)
if result.Mode != Automotive { if result.Mode != Automotive {
t.Fatalf("Mode is not Automotive") t.Fatalf("Mode is not Automotive")
} }
@ -35,7 +60,7 @@ func TestParseAllValues(t *testing.T) {
if result.VoutActual != float32(5.031) { if result.VoutActual != float32(5.031) {
t.Fatalf("VoutActual is not 5.031") t.Fatalf("VoutActual is not 5.031")
} }
res2 := Peripheralst{Out_sw_vin: true, Out_start_output:true, Out_Psw:false, Out_Led:true, In_vout_good: true} res2 := Peripheralst{OutSwVin: true, OutStartOutput:true, OutPsw:false, OutLed:true, InVoutGood: true}
if result.Peripherals != res2 { if result.Peripherals != res2 {
t.Fatalf("Peripherals is not Correct: %+v", result.Peripherals) t.Fatalf("Peripherals is not Correct: %+v", result.Peripherals)
} }
@ -82,12 +107,13 @@ func TestParseAllValues(t *testing.T) {
func TestParseAllValues2(t *testing.T) { func TestParseAllValues2(t *testing.T) {
var test1 = []byte{130, 133, 8, 76, 0, 43, 27, 133, 205, 251, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 127, 0, 0, 167} var test1 = []byte{130, 133, 8, 76, 0, 43, 27, 133, 205, 251, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 127, 0, 0, 167}
dc := Dcdc200{} dc := DcDcUSB{}
dc.Init()
result, err := dc.parseAllValues(test1, 24) result, err := dc.parseAllValues(test1, 24)
if err != nil { if err != nil {
t.Fatalf("Error Returned from parseAllValues: %v", err) t.Fatalf("Error Returned from parseAllValues: %v", err)
} }
t.Logf("Param %+v", result) // t.Logf("Param %+v", result)
if result.Mode != Automotive { if result.Mode != Automotive {
t.Fatalf("Mode is not Automotive") t.Fatalf("Mode is not Automotive")
} }
@ -110,7 +136,7 @@ func TestParseAllValues2(t *testing.T) {
if result.VoutActual != float32(5.031) { if result.VoutActual != float32(5.031) {
t.Fatalf("VoutActual is not 5.031") t.Fatalf("VoutActual is not 5.031")
} }
res2 := Peripheralst{Out_sw_vin: true, Out_start_output:true, Out_Psw:false, Out_Led:true, In_vout_good: true} res2 := Peripheralst{OutSwVin: true, OutStartOutput:true, OutPsw:false, OutLed:true, InVoutGood: true}
if result.Peripherals != res2 { if result.Peripherals != res2 {
t.Fatalf("Peripherals is not Correct: %+v", result.Peripherals) t.Fatalf("Peripherals is not Correct: %+v", result.Peripherals)
} }
@ -157,12 +183,13 @@ func TestParseAllValues2(t *testing.T) {
func TestParseAllValues3(t *testing.T) { func TestParseAllValues3(t *testing.T) {
var test1 = []byte{130, 133, 8, 76, 0, 44, 25, 133, 205, 251, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167} var test1 = []byte{130, 133, 8, 76, 0, 44, 25, 133, 205, 251, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}
dc := Dcdc200{} dc := DcDcUSB{}
dc.Init()
result, err := dc.parseAllValues(test1, 24) result, err := dc.parseAllValues(test1, 24)
if err != nil { if err != nil {
t.Fatalf("Error Returned from parseAllValues: %v", err) t.Fatalf("Error Returned from parseAllValues: %v", err)
} }
t.Logf("Param %+v", result) // t.Logf("Param %+v", result)
if result.Mode != Automotive { if result.Mode != Automotive {
t.Fatalf("Mode is not Automotive") t.Fatalf("Mode is not Automotive")
} }
@ -185,7 +212,7 @@ func TestParseAllValues3(t *testing.T) {
if result.VoutActual != float32(5.148) { if result.VoutActual != float32(5.148) {
t.Fatalf("VoutActual is not 5.148") t.Fatalf("VoutActual is not 5.148")
} }
res2 := Peripheralst{Out_sw_vin: true, Out_start_output:true, Out_Psw:false, Out_Led:false, In_vout_good: true} res2 := Peripheralst{OutSwVin: true, OutStartOutput:true, OutPsw:false, OutLed:false, InVoutGood: true}
if result.Peripherals != res2 { if result.Peripherals != res2 {
t.Fatalf("Peripherals is not Correct: %+v", result.Peripherals) t.Fatalf("Peripherals is not Correct: %+v", result.Peripherals)
} }
@ -231,12 +258,13 @@ func TestParseAllValues3(t *testing.T) {
} }
func TestParseAllValues4(t *testing.T) { func TestParseAllValues4(t *testing.T) {
var test1 = []byte{130, 133, 16, 76, 0, 44, 27, 133, 205, 247, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 167} var test1 = []byte{130, 133, 16, 76, 0, 44, 27, 133, 205, 247, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 167}
dc := Dcdc200{} dc := DcDcUSB{}
dc.Init()
result, err := dc.parseAllValues(test1, 24) result, err := dc.parseAllValues(test1, 24)
if err != nil { if err != nil {
t.Fatalf("Error Returned from parseAllValues: %v", err) t.Fatalf("Error Returned from parseAllValues: %v", err)
} }
t.Logf("Param %+v", result) // t.Logf("Param %+v", result)
if result.Mode != Automotive { if result.Mode != Automotive {
t.Fatalf("Mode is not Automotive") t.Fatalf("Mode is not Automotive")
} }
@ -259,7 +287,7 @@ func TestParseAllValues4(t *testing.T) {
if result.VoutActual != float32(5.148) { if result.VoutActual != float32(5.148) {
t.Fatalf("VoutActual is not 5.148") t.Fatalf("VoutActual is not 5.148")
} }
res2 := Peripheralst{Out_sw_vin: true, Out_start_output:true, Out_Psw:false, Out_Led:true, In_vout_good: true} res2 := Peripheralst{OutSwVin: true, OutStartOutput:true, OutPsw:false, OutLed:true, InVoutGood: true}
if result.Peripherals != res2 { if result.Peripherals != res2 {
t.Fatalf("Peripherals is not Correct: %+v", result.Peripherals) t.Fatalf("Peripherals is not Correct: %+v", result.Peripherals)
} }
@ -306,12 +334,13 @@ func TestParseAllValues4(t *testing.T) {
func TestParseAllValues5(t *testing.T) { func TestParseAllValues5(t *testing.T) {
var test1 = []byte{130, 133, 16, 76, 0, 44, 9, 133, 205, 247, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167} var test1 = []byte{130, 133, 16, 76, 0, 44, 9, 133, 205, 247, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}
dc := Dcdc200{} dc := DcDcUSB{}
dc.Init()
result, err := dc.parseAllValues(test1, 24) result, err := dc.parseAllValues(test1, 24)
if err != nil { if err != nil {
t.Fatalf("Error Returned from parseAllValues: %v", err) t.Fatalf("Error Returned from parseAllValues: %v", err)
} }
t.Logf("Param %+v", result) //t.Logf("Param %+v", result)
if result.Mode != Automotive { if result.Mode != Automotive {
t.Fatalf("Mode is not Automotive") t.Fatalf("Mode is not Automotive")
} }
@ -334,7 +363,7 @@ func TestParseAllValues5(t *testing.T) {
if result.VoutActual != float32(5.148) { if result.VoutActual != float32(5.148) {
t.Fatalf("VoutActual is not 5.148") t.Fatalf("VoutActual is not 5.148")
} }
res2 := Peripheralst{Out_sw_vin: false, Out_start_output:true, Out_Psw:false, Out_Led:false, In_vout_good: true} res2 := Peripheralst{OutSwVin: false, OutStartOutput:true, OutPsw:false, OutLed:false, InVoutGood: true}
if result.Peripherals != res2 { if result.Peripherals != res2 {
t.Fatalf("Peripherals is not Correct: %+v", result.Peripherals) t.Fatalf("Peripherals is not Correct: %+v", result.Peripherals)
} }

26
dcdcusbexample_test.go Normal file
View file

@ -0,0 +1,26 @@
package dcdcusb_test
import (
"context"
"log"
"time"
"github.com/Fishwaldo/go-dcdc200"
)
func Example() {
dc := dcdcusb.DcDcUSB{}
dc.Init()
if ok, err := dc.Scan(); !ok {
log.Fatalf("Scan Failed: %v", err)
return
}
defer dc.Close()
for i := 0; i < 100; i++ {
ctx, cancel := context.WithTimeout(context.Background(), (1 * time.Second))
dc.GetAllParam(ctx)
cancel()
time.Sleep(1 * time.Second)
}
dc.Close()
}

View file

@ -1,88 +1,112 @@
package dcdc200 /*
MIT License
Copyright (c) 2021 Justin Hammond
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package dcdcusb
const ( const (
DCDC200_VID = 0x04d8 dcdc200_vid = 0x04d8
DCDC200_PID = 0xd003 dcdc200_pid = 0xd003
) )
const ( const (
StatusOK = 0x00 statusOK = 0x00
StatusErase = 0x01 statusErase = 0x01
StatusWrite = 0x02 statusWrite = 0x02
StatusRead = 0x03 statusRead = 0x03
StatusError = 0xFF statusError = 0xFF
) )
const ( const (
CmdGetAllValues = 0x81 cmdGetAllValues = 0x81
CmdRecvAllValues = 0x82 cmdRecvAllValues = 0x82
CmdOut = 0xB1 cmdOut = 0xB1
CmdIn = 0xB2 cmdIn = 0xB2
CmdReadOut = 0xA1 cmdReadOut = 0xA1
CmdReadIn = 0xA2 cmdReadIn = 0xA2
CmdWriteOut = 0xA3 cmdWriteOut = 0xA3
CmdWriteIn = 0xA4 cmdWriteIn = 0xA4
CmdErase = 0xA5 cmdErase = 0xA5
) )
const ( const (
MsgInternal = 0xFF msgInternal = 0xFF
MsgInternalDisconnected = 0x01 msgInternalDisconnected = 0x01
) )
const ( const (
CmdSetAuxWin = 0x01 cmdSetAuxWin = 0x01
CmdSetPwSwitch = 0x02 cmdSetPwSwitch = 0x02
CmdSetOutput = 0x03 cmdSetOutput = 0x03
CmdWriteVout = 0x06 cmdWriteVout = 0x06
CmdReadVout = 0x07 cmdReadVout = 0x07
CmdIncVout = 0x0C cmdIncVout = 0x0C
CmdDecVout = 0x0D cmdDecVout = 0x0D
CmdLoadDefaults = 0x0E cmdLoadDefaults = 0x0E
CmdScriptStart = 0x10 cmdScriptStart = 0x10
CmdScriptStop = 0x11 cmdScriptStop = 0x11
CmdSleep = 0x12 cmdSleep = 0x12
CmdReadRegulatorStep = 0x13 cmdReadRegulatorStep = 0x13
) )
const ( const (
TypeCodeMemory = 0x00 typeCodeMemory = 0x00
TypeEepromExternal = 0x01 typeEepromExternal = 0x01
TypeEepromInternal = 0x02 typeEepromInternal = 0x02
TypeCodeSplash = 0x03 typeCodeSplash = 0x03
) )
const ( const (
FlashReportEraseMemory = 0xF2 /* AddressLo : AddressHi : AddressUp (anywhere inside the 64 byte-block to be erased) */ flashReportEraseMemory = 0xF2 /* AddressLo : AddressHi : AddressUp (anywhere inside the 64 byte-block to be erased) */
FlashReportReadMemory = 0xF3 /* AddressLo : AddressHi : AddressUp : Data Length (1...32) */ flashReportReadMemory = 0xF3 /* AddressLo : AddressHi : AddressUp : Data Length (1...32) */
FlashReportWriteMemory = 0xF4 /* AddressLo : AddressHi : AddressUp : Data Length (1...32) : Data.... */ flashReportWriteMemory = 0xF4 /* AddressLo : AddressHi : AddressUp : Data Length (1...32) : Data.... */
KeyBdReportEraseMemory = 0xB2 /* same as F2 but in keyboard mode */ keyBdReportEraseMemory = 0xB2 /* same as F2 but in keyboard mode */
KeybdReportReadMemory = 0xB3 /* same as F3 but in keyboard mode */ keybdReportReadMemory = 0xB3 /* same as F3 but in keyboard mode */
KeybdReportWriteMemory = 0xB4 /* same as F4 but in keyboard mode */ keybdReportWriteMemory = 0xB4 /* same as F4 but in keyboard mode */
KeybdReportMemory = 0x41 /* response to b3,b4 */ keybdReportMemory = 0x41 /* response to b3,b4 */
) )
const ( const (
InReportExtEEData = 0x31 inReportExtEEData = 0x31
OutReportExtEERead = 0xA1 outReportExtEERead = 0xA1
OutReportExtEEWrite = 0xA2 outReportExtEEWrite = 0xA2
InReportIntEEData = 0x32 inReportIntEEData = 0x32
OutReportIntEERead = 0xA3 outReportIntEERead = 0xA3
OutReportIntEEWrite = 0xA4 outReportIntEEWrite = 0xA4
) )
/* MEASUREMENT CONSTANTS */ /* MEASUREMENT CONSTANTS */
const ( const (
CT_RW = 75 ct_RW = 75
CT_R1 = 49900 ct_R1 = 49900
CT_R2 = 1500 ct_R2 = 1500
CT_RP = 10000 ct_RP = 10000
) )
const CHECK_CHAR = 0xAA /* used for line/write check */ const check_char = 0xAA /* used for line/write check */
const MAX_MESSAGE_CNT = 64 const max_message_cnt = 64
//go:generate stringer -type=DcdcModet //go:generate stringer -type=DcdcModet
type DcdcModet int type DcdcModet int

34
doc.go Normal file
View file

@ -0,0 +1,34 @@
/*
MIT License
Copyright (c) 2021 Justin Hammond
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
Package go-dcdcusb interfaces with the DCDCUSB power supply from mini-box (https://www.mini-box.com/DCDC-USB)
via USB port and allows you to retrive the status of the power supply
it depends upon GoUSB which in turn depends upon the libusb C library, thus CGO is required for this module
Please see the GoUSB pages for hints on compiling for platforms other than linux
*/
package dcdcusb

5
go.mod
View file

@ -2,4 +2,7 @@ module github.com/Fishwaldo/go-dcdc200
go 1.17 go 1.17
require github.com/google/gousb v1.1.1 require (
github.com/Fishwaldo/go-logadapter v0.0.2
github.com/google/gousb v1.1.1
)

59
go.sum
View file

@ -1,2 +1,61 @@
github.com/Fishwaldo/go-logadapter v0.0.2 h1:RxFOr+bEDqQ1rPUmjUX5u8fGLCKY0Lyea+9AxDqzaW4=
github.com/Fishwaldo/go-logadapter v0.0.2/go.mod h1:aRbQ8rWdpeD0WWo241ctqgk/yRto8Axg09EkwWiVGK0=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/gousb v1.1.1 h1:2sjwXlc0PIBgDnXtNxUrHcD/RRFOmAtRq4QgnFBE6xc= github.com/google/gousb v1.1.1 h1:2sjwXlc0PIBgDnXtNxUrHcD/RRFOmAtRq4QgnFBE6xc=
github.com/google/gousb v1.1.1/go.mod h1:b3uU8itc6dHElt063KJobuVtcKHWEfFOysOqBNzHhLY= github.com/google/gousb v1.1.1/go.mod h1:b3uU8itc6dHElt063KJobuVtcKHWEfFOysOqBNzHhLY=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

280
usbif.go
View file

@ -1,280 +0,0 @@
package dcdc200
import (
"fmt"
"log"
"time"
"context"
"errors"
"github.com/google/gousb"
)
type Dcdc200 struct {
ctx *gousb.Context
dev *gousb.Device
intf *gousb.Interface
done func()
}
type TimerConfigt struct {
OffDelay time.Duration
HardOff time.Duration
}
type Peripheralst struct {
Out_sw_vin bool
Out_start_output bool
Out_Psw bool
Out_Led bool
In_vout_good bool
}
type Params struct {
VoutSet float32
VoutConfig float32
Vin float32
Vign float32
VoutActual float32
Peripherals Peripheralst
Output bool
AuxVIn bool
Version string
State DcdcStatet
CfgRegisters byte
VoltFlags byte
TimerFlags byte
//Timer int
TimerConfig TimerConfigt
//VoltConfig byte
TimerWait time.Duration
TimerVOut time.Duration
TimerVAux time.Duration
TimerPRWSW time.Duration
TimerSoftOff time.Duration
TimerHardOff time.Duration
ScriptPointer byte
Mode DcdcModet
}
func (dc *Dcdc200) Scan() (bool, error) {
dc.ctx = gousb.NewContext()
dc.ctx.Debug(10)
var err error
dc.dev, err = dc.ctx.OpenDeviceWithVIDPID(DCDC200_VID, DCDC200_PID)
if err != nil {
log.Printf("Could Not Open Device: %v", err)
dc.Close()
return false, err
}
if dc.dev == nil {
log.Printf("Can't Find Device")
dc.Close()
return false, nil
}
err = dc.dev.SetAutoDetach(true)
if err != nil {
log.Fatalf("%s.SetAutoDetach(true): %v", dc.dev, err)
}
confignum, _ := dc.dev.ActiveConfigNum()
log.Printf("Device Config: %s %d", dc.dev.String(), confignum)
// desc, _ := dc.dev.GetStringDescriptor(1)
// manu, _ := dc.dev.Manufacturer()
// prod, _ := dc.dev.Product()
// serial, _ := dc.dev.SerialNumber()
dc.intf, dc.done, err = dc.dev.DefaultInterface()
if err != nil {
log.Printf("%s.Interface(): %v", dc.dev, err)
dc.Close()
return false, err
}
log.Printf("Interface: %s", dc.intf.String())
return true, nil
}
func (dc *Dcdc200) Close() {
if dc.intf != nil {
dc.done()
dc.intf.Close()
}
if dc.dev != nil {
dc.dev.Close()
}
if dc.ctx != nil {
dc.ctx.Close()
}
}
func (dc *Dcdc200) GetAllParam(ctx context.Context) {
if dc.intf == nil {
log.Fatalf("Interface Not Opened")
return
}
outp, err := dc.intf.OutEndpoint(0x01)
if err != nil {
log.Fatalf("Can't Get OutPoint: %s", err)
return;
}
//log.Printf("OutEndpoint: %v", outp)
var send = make([]byte, 24)
send[0] = CmdGetAllValues
//send = append(send, 0)
//log.Printf("About to Send %v", send)
len, err := outp.WriteContext(ctx, send)
if err != nil {
log.Fatalf("Cant Send GetAllValues Command: %s (%v) - %d", err, send, len)
return
}
//log.Printf("Sent %d Bytes", len)
inp, err := dc.intf.InEndpoint(0x81)
if err != nil {
log.Fatalf("Can't Get OutPoint: %s", err)
return;
}
//log.Printf("InEndpoint: %v", inp)
var recv = make([]byte, 24)
len, err = inp.ReadContext(ctx, recv)
if err != nil {
log.Fatalf("Can't Read GetAllValues Command: %s", err)
return
}
//log.Printf("Got %d Bytes", len)
log.Printf("Got %v", recv)
dc.parseAllValues(recv, len)
}
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
//ignition connect: 2021/09/20 15:51:38 Got [130 133 7 76 75 43 27 133 215 251 1 0 0 0 0 0 0 0 0 3 68 0 0 167]
//ignition connect2 2021/09/20 15:52:14 Got [130 133 7 76 75 44 27 133 215 251 1 0 0 0 0 0 0 0 0 3 32 0 0 167]
//ignition disconnect: 2021/09/20 15:50:39 Got [130 133 8 76 0 43 27 133 205 251 1 0 0 0 0 0 0 0 0 3 127 0 0 167]
// 2021/09/20 16:12:54 Got [130 133 8 76 0 44 25 133 205 251 1 0 0 0 0 0 0 0 0 0 0 0 0 167]
// 2021/09/20 16:12:56 Got [130 133 16 76 0 44 27 133 205 247 1 0 0 0 0 0 0 0 0 0 0 0 59 167]
// 2021/09/20 16:13:54 Got [130 133 16 76 0 44 9 133 205 247 1 0 0 0 0 0 0 0 0 0 0 0 0 167]
func (dc *Dcdc200) parseAllValues(buf []byte, len int) (Params, error){
switch buf[0] {
case CmdRecvAllValues:
param := Params{}
param.Mode = dc.modeToConst((buf[1] >> 6) & 0x7)
param.VoutConfig = dc.voutConfigtoFloat((buf[1] >> 2) & 0x07)
param.TimerConfig = dc.timerConfigToDuration(buf[1] & 0x03)
param.State = dc.stateToConst(buf[2])
param.Vin = float32(buf[3]) * float32(0.1558)
param.Vign = float32(buf[4]) * float32(0.1558)
param.VoutActual = float32(buf[5]) * float32(0.1170)
param.Peripherals = dc.peripheralsState(buf[6])
param.CfgRegisters = buf[7]
param.VoltFlags = buf[8]
param.TimerFlags = buf[9]
param.ScriptPointer = buf[10]
param.Version = fmt.Sprintf("%d.%d", int((buf[23] >> 5) & 0x07), int(buf[23]) & 0x1F)
param.TimerWait = dc.convertTime(buf[11:13])
param.TimerVOut = dc.convertTime(buf[13:15])
param.TimerVAux = dc.convertTime(buf[15:17])
param.TimerPRWSW = dc.convertTime(buf[17:19])
param.TimerSoftOff = dc.convertTime(buf[19:21])
param.TimerHardOff = dc.convertTime(buf[21:23])
fmt.Printf("%+v\n", param)
return param, nil
}
return Params{}, errors.New("unknown command recieved")
}
func (dc *Dcdc200) modeToConst(mode byte) (DcdcModet) {
switch mode {
case 0:
return Dumb
case 1:
return Script
case 2:
return Automotive
case 3:
return UPS
default:
return Unknown
}
}
func (dc *Dcdc200) voutConfigtoFloat (config byte) (float32) {
switch config {
case 0:
return float32(12.0)
case 1:
return float32(5.0)
case 2:
return float32(6.0)
case 3:
return float32(9.0)
case 4:
return float32(13.5)
case 5:
return float32(16.0)
case 6:
return float32(19.0)
case 7:
return float32(24.0)
default:
return float32(-1)
}
}
func (dc Dcdc200) timerConfigToDuration(config byte) (TimerConfigt) {
switch config {
case 0:
return TimerConfigt{OffDelay: 0, HardOff: 0}
case 1:
return TimerConfigt{OffDelay: 15 * time.Minute, HardOff: 1 * time.Minute}
case 2:
return TimerConfigt{OffDelay: 5 * time.Second, HardOff: -1}
case 3:
return TimerConfigt{OffDelay: 30 * time.Minute, HardOff: 1 * time.Minute}
case 4:
return TimerConfigt{OffDelay: 5 * time.Second, HardOff: 1 * time.Minute}
case 5:
return TimerConfigt{OffDelay: 15 * time.Minute, HardOff: -1}
case 6:
return TimerConfigt{OffDelay: 1 * time.Minute, HardOff: 1 * time.Minute}
case 7:
return TimerConfigt{OffDelay: 1 * time.Hour, HardOff: -1}
default:
return TimerConfigt{OffDelay: -1, HardOff: -1}
}
}
func (dc Dcdc200) stateToConst(state byte) (DcdcStatet) {
switch state {
case 7:
return StateOk
case 8:
return StateIgnOff
case 16:
return StateHardOffCountdown
default:
return StateUnknown
}
}
func (dc Dcdc200) peripheralsState(state byte) (Peripheralst) {
p := Peripheralst {
In_vout_good: ((state & 0x01) != 0),
Out_Led: ((state & 0x02) != 0),
Out_Psw: ((state & 0x04) != 0),
Out_start_output: ((state & 0x08) != 0),
Out_sw_vin: ((state & 0x10) != 0),
}
return p
}
func (dc Dcdc200) convertTime(raw []byte) (time.Duration) {
duration := int64(raw[0]) << 8
duration += int64(raw[1])
return time.Duration(duration * int64(time.Second))
}