Skip to content

Commit

Permalink
Merge pull request #3 from kinglevel/main
Browse files Browse the repository at this point in the history
Fix missing spectra datapoints; Improve docs and command example
  • Loading branch information
akares authored Nov 5, 2024
2 parents b77906d + b40954f commit 6190ea3
Show file tree
Hide file tree
Showing 4 changed files with 288 additions and 44 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
coverage.out
coverage.html
/tmp
skread
108 changes: 103 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Based on original C# SDK for Windows from SEKONIC.

- Sekonic C-700
- Sekonic C-800
- Sekonic C-800-U (US Version. Basically the same as C-800)
- Sekonic C-7000 (supports extended measurement configuration: FOV and Exposure Time)

## Supported (tested) platforms
Expand All @@ -20,7 +21,15 @@ Based on original C# SDK for Windows from SEKONIC.
- Windows
- Linux

## Dependencies
## Known limitations

Currently **only ambient** measuring mode is supported.

TM-30, SSI and TLCI measurements are available for Sekonic C-7000 with FW version > 25 but parsing of these fields is **not implemented yet**.

## Usage

### Install USB driver

Default implementation uses [gousb](https://github.com/google/gousb) wrapper for the libusb library.

Expand All @@ -29,18 +38,107 @@ You must have [libusb-1.0](https://github.com/libusb/libusb/wiki) installed on y
Installation for different platforms is covered in
[gousb documentation](https://github.com/google/gousb/blob/master/README.md#dependencies).

_If you use Linux, you probably already have it._
_If you use Mac ot Windows and was using USB devices that needed custom driver, you also probably have it._

_Alternatively_ you can provide custom USB implementation with [simple interface](usbadapter.go) close to io.Reader. See the default [gousb based implementation](gousb_adapter.go) for reference.

## SDK usage
### Install Go

You need `Go` programming language to be installed first.

See the Go's [Download and install](https://go.dev/doc/install) page for installation instructions for different OS.

On MacOS just use [Homebrew](https://brew.sh/):

```
homebrew install go
```

### Run example measurement program usung Go

1. Connect your device.

2. Run commands below:

See the [skread](cmd/skread/main.go) command implementation.
```
go run ./cmd/skread -run -all
```

```
go run ./cmd/skread -help
```

_Go will take care of dependencies when running this script for the first time._

### Build standalone program executable (if needed)

## Run example
```
go build ./cmd/skread
```

_This will create binary executable file named `skread` in the same directory._

Run the executable:

```
go run ./cmd/skread
./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._

### Create your own measurement program (if needed)

Note: the [cmd/skread/main.go](cmd/skread/main.go) is just an example of the library usage. If more specific funtionality is needed, you always can create your own Go program and import the library in the same way as example does. Go will fetch it automatically.

Example:

1. Create your project dir:

```
mkdir my_skreader && cd my_skreader
```

2. Initialise Go module named `my_skreader` and add `skreader` library as an external dependency:

```
go mod init my_skreader
go get github.com/akares/skreader
```

3. Download `main.go` example file there (or create manually):

```
curl -OL https://raw.githubusercontent.com/akares/skreader/main/cmd/skread/main.go
```

4. Run:

```
go run . -help
```

5. _Modify the program according to your needs._

6. Build standalone executable (if needed):

```
go build -o my_skreader ./main.go
./my_skreader -help
```

_You will still need to take care of the USB driver dependency mentioned earlier._

## Library API

See the [skread](cmd/skread/main.go) command implementation for details.

## Contribution

1. Use `gofmt`
2. Ensure unit tests are okay: `go test ./...`
3. Ensure Go linter finds no errors: `golangci-lint run .`

## License

This project is licensed under the terms of the MIT license.
Expand Down
187 changes: 156 additions & 31 deletions cmd/skread/main.go
Original file line number Diff line number Diff line change
@@ -1,49 +1,174 @@
package main

import (
"flag"
"fmt"
"os"
"strconv"

"github.com/akares/skreader"
)

//nolint:funlen,gocyclo
func main() {
// Connect to SEKONIC device.
sk, err := skreader.NewDeviceWithAdapter(&skreader.GousbAdapter{})
if err != nil {
panic(err)
}
defer sk.Close()
// 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")

// Shown by default if no other flag is set
showLDi := flag.Bool("LDi", false, "Shows the most interesting data for LDs")

// Get some basic info of the device.
model, _ := sk.ModelName()
fw, _ := sk.FirmwareVersion()
flag.Parse()

fmt.Println(strconv.Quote(sk.String()))
fmt.Println("MN:", strconv.Quote(model))
fmt.Println("FW:", fw)
if *help || len(os.Args) == 1 {
fmt.Println("Usage: skreader [options]")
fmt.Println("Example: skreader -run -all")
fmt.Println("\nOptions:")
flag.PrintDefaults()

os.Exit(0)
}

// Get the current operational mode, knobs and buttons states of the device.
st, err := sk.State()
if err != nil {
panic(err)
if *run && len(os.Args) == 2 {
*showLDi = true
}
fmt.Printf("ST: %+v\n", st)

// Run one measurement.
meas, err := sk.Measure()
if err != nil {
panic(err)
if *showAll {
*showInfo = true
*showIlluminance = true
*showColorTemperature = true
*showTristimulus = true
*showCIE1931 = true
*showCIE1976 = true
*showDWL = true
*show = true
*showSpectra1nm = true
*showSpectra5nm = true
}

// Print the measurement result in various vays.
fmt.Printf("Meas: %s\n", meas.Repr())
fmt.Printf("Meas: %s\n", meas.String())
fmt.Printf(
"Lux=%s x=%s y=%s CCT=%s\n",
meas.Illuminance.Lux.Str,
meas.CIE1931.X.Str,
meas.CIE1931.Y.Str,
meas.ColorTemperature.Tcp.Str,
)
if *run {
// Connect to SEKONIC device.
sk, err := skreader.NewDeviceWithAdapter(&skreader.GousbAdapter{})
if err != nil {
panic(err)
}
defer sk.Close()

// Get some basic info of the device.
model, _ := sk.ModelName()
fw, _ := sk.FirmwareVersion()

// Get the current operational mode, knobs and buttons states of the device.
st, err := sk.State()
if err != nil {
panic(err)
}

// 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)
}

// Run one measurement.
meas, err := sk.Measure()
if err != nil {
panic(err)
}

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 {
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 {
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 {
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 {
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 {
fmt.Printf("------------\n")
fmt.Printf("DominantWavelength:\n")
fmt.Printf("Wavelength: %s\n", meas.DWL.Wavelength)
fmt.Printf("ExcitationPurity: %s\n", meas.DWL.ExcitationPurity)
}

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])
}
}

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 *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 *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])
}
}
}
Loading

0 comments on commit 6190ea3

Please sign in to comment.