diff --git a/README.md b/README.md index 43732b8..1046fd1 100644 --- a/README.md +++ b/README.md @@ -59,14 +59,17 @@ homebrew install go 1. Connect your device. -2. Run commands below: +2. Run one measurement: ``` -go run ./cmd/skread -run -all +go run ./cmd/skread measure -s ``` +3. Get info about other available options: + ``` -go run ./cmd/skread -help +go run ./cmd/skread --help +go run ./cmd/skread measure --help ``` _Go will take care of dependencies when running this script for the first time._ @@ -82,7 +85,7 @@ _This will create binary executable file named `skread` in the same directory._ Run the executable: ``` -./skread -help +./skread --help ``` _Now you can run this file on any other machine with the same OS and architecture as the one you built it with. But remeber about USB driver dependency mentioned earlier, it is needed for program to run._ @@ -115,7 +118,7 @@ curl -OL https://raw.githubusercontent.com/akares/skreader/main/cmd/skread/main. 4. Run: ``` -go run . -help +go run . --help ``` 5. _Modify the program according to your needs._ @@ -124,7 +127,7 @@ go run . -help ``` go build -o my_skreader ./main.go -./my_skreader -help +./my_skreader --help ``` _You will still need to take care of the USB driver dependency mentioned earlier._ diff --git a/cmd/skread/main.go b/cmd/skread/main.go index 8799e0f..d8166cd 100644 --- a/cmd/skread/main.go +++ b/cmd/skread/main.go @@ -1,174 +1,283 @@ package main import ( - "flag" "fmt" + "log" "os" - "strconv" "github.com/akares/skreader" + "github.com/urfave/cli/v2" ) -//nolint:funlen,gocyclo -func main() { - // Available commands - help := flag.Bool("help", false, "Shows usage information") - run := flag.Bool("run", false, "Runs a normal measurement and outputs the selected data") - - // Data to show - showInfo := flag.Bool("info", false, "Shows info about the connected device") - showAll := flag.Bool("all", false, "Shows all data from the connected device") - showIlluminance := flag.Bool("Illuminance", false, "Shows illuminance data") - showColorTemperature := flag.Bool("ColorTemperature", false, "Shows ColorTemperature data") - showTristimulus := flag.Bool("Tristimulus", false, "Shows Tristimulus data") - showCIE1931 := flag.Bool("CIE1931", false, "Shows CIE1931 data") - showCIE1976 := flag.Bool("CIE1976", false, "Shows CIE1976 data") - showDWL := flag.Bool("DWL", false, "Shows DWL data") - show := flag.Bool("CRI", false, "Shows CRI data") - showSpectra1nm := flag.Bool("Spectra1nm", false, "Shows Spectra1nm data") - showSpectra5nm := flag.Bool("Spectra5nm", false, "Shows Spectra5nm data") +const ( + name = "skreader" + version = "0.2.0" + description = "command line tool for SEKONIC spectrometers remote control" +) - // Shown by default if no other flag is set - showLDi := flag.Bool("LDi", false, "Shows the most interesting data for LDs") +func skConnect() (*skreader.Device, error) { + sk, err := skreader.NewDeviceWithAdapter(&skreader.GousbAdapter{}) + if err != nil { + return nil, err + } - flag.Parse() + return sk, nil +} - if *help || len(os.Args) == 1 { - fmt.Println("Usage: skreader [options]") - fmt.Println("Example: skreader -run -all") - fmt.Println("\nOptions:") - flag.PrintDefaults() +func infoCmd(_ *cli.Context) error { + sk, err := skConnect() + if err != nil { + return err + } + defer sk.Close() - os.Exit(0) + st, err := sk.State() + if err != nil { + return err } - if *run && len(os.Args) == 2 { - *showLDi = true + model, _ := sk.ModelName() + fw, _ := sk.FirmwareVersion() + + fmt.Println("Device:", sk.String()) + fmt.Println("Model:", model) + fmt.Println("Firmware:", fw) + fmt.Println("Status:", st.Status) + fmt.Println("Remote:", st.Remote) + fmt.Println("Button:", st.Button, st.Ring) + fmt.Println("Ring:", st.Ring) + + return nil +} + +//nolint:gocyclo,funlen +func measureCmd(c *cli.Context) error { + sk, err := skConnect() + if err != nil { + return err } + defer sk.Close() - if *showAll { - *showInfo = true - *showIlluminance = true - *showColorTemperature = true - *showTristimulus = true - *showCIE1931 = true - *showCIE1976 = true - *showDWL = true - *show = true - *showSpectra1nm = true - *showSpectra5nm = true + meas, err := sk.Measure() + if err != nil { + panic(err) } - if *run { - // Connect to SEKONIC device. - sk, err := skreader.NewDeviceWithAdapter(&skreader.GousbAdapter{}) - if err != nil { - panic(err) - } - defer sk.Close() + verbose := c.Bool("verbose") - // Get some basic info of the device. - model, _ := sk.ModelName() - fw, _ := sk.FirmwareVersion() + showIlluminance := c.Bool("illuminance") || c.Bool("all") || c.Bool("simple") + showColorTemperature := c.Bool("color-temperature") || c.Bool("all") || c.Bool("simple") + showTristimulus := c.Bool("tristimulus") || c.Bool("all") || c.Bool("simple") + showCIE1931 := c.Bool("cie1931") || c.Bool("all") || c.Bool("simple") + showCIE1976 := c.Bool("cie1976") || c.Bool("all") || c.Bool("simple") + showDWL := c.Bool("dwl") || c.Bool("all") || c.Bool("simple") - // Get the current operational mode, knobs and buttons states of the device. - st, err := sk.State() - if err != nil { - panic(err) - } + showCRI := c.Bool("cri") || c.Bool("all") + showSpectra1nm := c.Bool("spectra1nm") || c.Bool("all") + showSpectra5nm := c.Bool("spectra5nm") || c.Bool("all") - // Print the device info - if *showInfo { - fmt.Println(strconv.Quote(sk.String())) - fmt.Println("Model:", strconv.Quote(model)) - fmt.Println("Firmware:", fw) - fmt.Printf("State: %+v\n", st) - } + // Shown by default if no other flag is set + showLDi := c.Bool("ldi") || c.Bool("all") || (!showIlluminance && !showColorTemperature && !showTristimulus && !showCIE1931 && !showCIE1976 && !showDWL && !showCRI && !showSpectra1nm && !showSpectra5nm) - // Run one measurement. - meas, err := sk.Measure() - if err != nil { - panic(err) + if showIlluminance { + if verbose { + fmt.Println("------------") + fmt.Println("Illuminance:") } + fmt.Println("LUX:", meas.Illuminance.Lux.Str) + fmt.Println("Fc:", meas.Illuminance.FootCandle) + } - if *showIlluminance { - fmt.Printf("------------\n") - fmt.Printf("Illuminance:\n") - fmt.Printf("LUX: %s\n", meas.Illuminance.Lux.Str) - fmt.Printf("Fc: %s\n", meas.Illuminance.FootCandle) + if showColorTemperature { + if verbose { + fmt.Println("------------") + fmt.Println("ColorTemperature:") } + fmt.Println("CCT:", meas.ColorTemperature.Tcp) + fmt.Println("CCT DeltaUv:", meas.ColorTemperature.DeltaUv) + } - if *showColorTemperature { - fmt.Printf("------------\n") - fmt.Printf("ColorTemperature:\n") - fmt.Printf("CCT: %s\n", meas.ColorTemperature.Tcp) - fmt.Printf("CCT DeltaUv: %s\n", meas.ColorTemperature.DeltaUv) + if showTristimulus { + if verbose { + fmt.Println("------------") + fmt.Println("Tristimulus:") } + fmt.Println("X:", meas.Tristimulus.X) + fmt.Println("Y:", meas.Tristimulus.Y) + fmt.Println("Z:", meas.Tristimulus.Z) + } - if *showTristimulus { - fmt.Printf("------------\n") - fmt.Printf("Tristimulus:\n") - fmt.Printf("X: %s\n", meas.Tristimulus.X) - fmt.Printf("Y: %s\n", meas.Tristimulus.Y) - fmt.Printf("Z: %s\n", meas.Tristimulus.Z) + if showCIE1931 { + if verbose { + fmt.Println("------------") + fmt.Println("CIE1931:") } + fmt.Println("X:", meas.CIE1931.X) + fmt.Println("Y:", meas.CIE1931.Y) + } - if *showCIE1931 { - fmt.Printf("------------\n") - fmt.Printf("CIE1931:\n") - fmt.Printf("X: %s\n", meas.CIE1931.X) - fmt.Printf("Y: %s\n", meas.CIE1931.Y) + if showCIE1976 { + if verbose { + fmt.Println("CIE1976:") + fmt.Println("------------") } + fmt.Println("Ud:", meas.CIE1976.Ud) + fmt.Println("Vd:", meas.CIE1976.Vd) + } - if *showCIE1976 { - fmt.Printf("------------\n") - fmt.Printf("CIE1976:\n") - fmt.Printf("Ud: %s\n", meas.CIE1976.Ud) - fmt.Printf("Vd: %s\n", meas.CIE1976.Vd) + if showDWL { + if verbose { + fmt.Println("------------") + fmt.Println("DominantWavelength:") } + fmt.Println("DominantWavelength:", meas.DWL.Wavelength) + fmt.Println("ExcitationPurity:", meas.DWL.ExcitationPurity) + } - if *showDWL { - fmt.Printf("------------\n") - fmt.Printf("DominantWavelength:\n") - fmt.Printf("Wavelength: %s\n", meas.DWL.Wavelength) - fmt.Printf("ExcitationPurity: %s\n", meas.DWL.ExcitationPurity) + if showCRI { + if verbose { + fmt.Println("------------") + fmt.Println("CRI:") } - - if *show { - fmt.Printf("------------\n") - fmt.Printf("CRI:\n") - fmt.Printf("RA: %s\n", meas.ColorRenditionIndexes.Ra) - for i := range meas.ColorRenditionIndexes.Ri { - fmt.Printf("R%d: %s\n", i+1, meas.ColorRenditionIndexes.Ri[i]) - } + fmt.Println("RA:", meas.ColorRenditionIndexes.Ra) + for i := range meas.ColorRenditionIndexes.Ri { + fmt.Printf("R%d: %s\n", i+1, meas.ColorRenditionIndexes.Ri[i]) } + } - if *showSpectra1nm { - fmt.Printf("------------\n") - fmt.Printf("SpectralData 1nm:\n") - for i := range meas.SpectralData1nm { - // TODO: Missing one datapoint? - wavelength := 380 + i - fmt.Printf("%d,%f\n", wavelength, meas.SpectralData1nm[i].Val) - } + if showSpectra1nm { + if verbose { + fmt.Println("------------") + fmt.Println("SpectralData 1nm:") + } + for i := range meas.SpectralData1nm { + wavelength := 380 + i + fmt.Printf("%d,%f\n", wavelength, meas.SpectralData1nm[i].Val) } + } - if *showSpectra5nm { - fmt.Printf("------------\n") - fmt.Printf("SpectralData 5nm:\n") - for i := range meas.SpectralData5nm { - // TODO: Missing one datapoint? - wavelength := 380 + (i * 5) - fmt.Printf("%d,%f\n", wavelength, meas.SpectralData5nm[i].Val) - } + if showSpectra5nm { + if verbose { + fmt.Println("------------") + fmt.Println("SpectralData 5nm:") + } + for i := range meas.SpectralData5nm { + wavelength := 380 + (i * 5) + fmt.Printf("%d,%f\n", wavelength, meas.SpectralData5nm[i].Val) } + } - if *showLDi { - fmt.Printf("LUX: %s\n", meas.Illuminance.Lux.Str) - fmt.Printf("CCT: %s\n", meas.ColorTemperature.Tcp) - fmt.Printf("CCT DeltaUv: %s\n", meas.ColorTemperature.DeltaUv) - fmt.Printf("RA: %s\n", meas.ColorRenditionIndexes.Ra) - fmt.Printf("R9: %s\n", meas.ColorRenditionIndexes.Ri[8]) + if showLDi { + if verbose { + fmt.Println("------------") } + fmt.Println("LUX:", meas.Illuminance.Lux.Str) + fmt.Println("CCT:", meas.ColorTemperature.Tcp) + fmt.Println("CCT DeltaUv:", meas.ColorTemperature.DeltaUv) + fmt.Println("RA:", meas.ColorRenditionIndexes.Ra) + fmt.Println("R9:", meas.ColorRenditionIndexes.Ri[8]) + } + + return nil +} + +//nolint:exhaustruct +func main() { + app := &cli.App{ + Name: name, + Version: version, + Usage: description, + Suggest: true, + EnableBashCompletion: true, + UseShortOptionHandling: true, + Commands: []*cli.Command{ + { + Name: "info", + Usage: "Shows info about the connected device.", + Action: infoCmd, + }, + { + Name: "measure", + Usage: "Runs one measurement and outputs the selected data.", + Action: measureCmd, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "ldi", + Aliases: []string{"l"}, + Usage: "include the most interesting data for LDs", + }, + &cli.BoolFlag{ + Name: "all", + Aliases: []string{"a"}, + Usage: "include all measurement data", + }, + &cli.BoolFlag{ + Name: "simple", + Aliases: []string{"s"}, + Usage: "include all simple measurement data (excluding spectra and CRI)", + }, + &cli.BoolFlag{ + Name: "illuminance", + Aliases: []string{"ill", "i"}, + Usage: "include illuminance values in Lux and foot-candle units", + }, + &cli.BoolFlag{ + Name: "color-temperature", + Aliases: []string{"cct", "c"}, + Usage: "include color temperature values in Kelvin and delta-uv units", + }, + &cli.BoolFlag{ + Name: "tristimulus", + Aliases: []string{"tri", "t"}, + Usage: "include tristimulus values in XYZ color space", + }, + &cli.BoolFlag{ + Name: "cie1931", + Aliases: []string{"xy", "x"}, + Usage: "include CIE1931 (x, y) chromaticity coordinates", + }, + &cli.BoolFlag{ + Name: "cie1976", + Aliases: []string{"uv", "u"}, + Usage: "include CIE1976 (u', v') chromaticity coordinates", + }, + &cli.BoolFlag{ + Name: "dwl", + Aliases: []string{"d"}, + Usage: "include dominant wavelength value", + }, + &cli.BoolFlag{ + Name: "cri", + Aliases: []string{"r"}, + Usage: "include CRI (Ra, Ri) values", + }, + &cli.BoolFlag{ + Name: "spectra1nm", + Aliases: []string{"1mm", "1"}, + Usage: "include spectral data for 1nm wavelength", + }, + &cli.BoolFlag{ + Name: "spectra5nm", + Aliases: []string{"5mm", "5"}, + Usage: "include spectral data for 5nm wavelength", + }, + &cli.BoolFlag{ + Name: "verbose", + Aliases: []string{"v"}, + Usage: "print more messages", + }, + }, + }, + }, + } + + cli.VersionFlag = &cli.BoolFlag{ + Name: "version", + Aliases: []string{"V"}, + Usage: "print only the version", + } + + if err := app.Run(os.Args); err != nil { + log.Fatal(err) } } diff --git a/go.mod b/go.mod index 44774ac..610d9e9 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,12 @@ require ( ) require ( + github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/stretchr/objx v0.5.1 // indirect + github.com/urfave/cli/v2 v2.27.5 // indirect + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 87b8087..345aa1b 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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= @@ -5,6 +7,8 @@ github.com/google/gousb v1.1.2 h1:1BwarNB3inFTFhPgUEfah4hwOPuDz/49I0uX8XNginU= github.com/google/gousb v1.1.2/go.mod h1:GGWUkK0gAXDzxhwrzetW592aOmkkqSGcj5KLEgmCVUg= 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/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -15,6 +19,10 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=