Drivers
Drivers are the services that the av-api calls to talk to physical AV devices. We write/use libraries that implement one of the interfaces in this package - which interface they implement depends on the type of device the driver is written for.
Subdirectories of this package are all of our BYU-specific driver servers, which are compiled into docker containers based on the dockerfile
(and the dockerfile-arm
for arm containers).
Writing a Driver
-
Create a new repo, titled with the control protocol or vendor
-driver
.-
Use the github provided Go
.gitignore
. -
Repos from BYU OIT AV should use the Apache 2.0 License
-
-
Clone your repo by running
git clone git@github.com:<org/repo>.git
All new repos should use go mod. Make sure to clone your repo outside of your $GOPATH
. -
Initialize go mod by running
go mod init <github.com/org/repo>
in your newly cloned repo. -
In a new file, create a struct in your new package that will implement the appropriate interface. Its fields should have data required to use the driver.
Each instantiation of your struct should semantically represent a specific device (IE a single projector) and as such should contain all of the information required to control that device package adcp (1) type Projector struct { Address string (2) Username string (2) Password string (2) }
1 A driver library should typically have only one package 2 Not required, just an example -
Implement all of the required functions in the matching interface found in this package. For example, to make a projector driver, you would probably want to implement the interface found in
display.go
.func (p *Projector) GetPower(ctx context.Context) (string, error) { (1) }
Make sure that your driver library has good test code to ensure future changes don’t break things. 😊 -
Once a working version of your library is ready, release a v1.0.0 version of it. For future releases, use semantic versioning to denote changes.
Err on the side of caution here. It’s ok to stay at V0.X for a while as things stabilize. Once you go V1, things will have to follow semantic far more strictly.
$ git tag -a "v1.0.0"
$ git push --tags
Creating a Driver Server
Once you have finished a library, or want to use one that implements one of the driver interfaces, you create create a driver server.
-
Create a subdirectory in this one with the name of your driver server. Usually, this should match the driver name, without the
-driver
suffix. -
In your new directory, initalize go mod by running
go mod init github.com/byuoitav/drivers/<folder name>
In this case, go mod is used to reliably import the correct version of external libraries, and not for exporting your package. -
Add the dockerfiles for both linux and arm to the directory
-
TODO anything else https://github.com/bwinterton needs to build these (makefiles, etc.)
-
Create a
server.go
file. This is where all of your driver server’s code should go.This will be changing shortly to represent new decisions. (TODO)
package main (1)
// imports
func main() { (1)
var port int
// variable declarations
pflag.IntVarP(&port, "port", "p", 80, "port to run the server on") (2)
// other flags
pflag.Parse() (3)
// create a net.Listener to run the server on
addr := fmt.Sprintf(":%d", port)
lis, err := net.Listen("tcp", addr)
if err != nil {
// handle err
}
// import driver library
display := &adcp.Projector{} (4)
// create server
server := drivers.CreateDisplayServer(display) (5)
if err = server.Serve(lis); err != nil {
// handle err
}
}
1 | Must be in package main with a main() function. This is where your driver server will start. |
2 | The port to run our servers will be passed in as part of the dockerfile. |
3 | We use the pflag library for POSIX style flags. |
4 | The variable, package, and struct name will change depending on the driver you are importing. |
5 | Use the correct Create…Server() function for the interface your driver implements. |