// // Copyright (c) 2018 // Mainflux // // SPDX-License-Identifier: Apache-2.0 // package sdk import ( "crypto/tls" "errors" "fmt" "net/http" ) const ( // CTJSON represents JSON content type. CTJSON ContentType = "application/json" // CTJSONSenML represents JSON SenML content type. CTJSONSenML ContentType = "application/senml+json" // CTBinary represents binary content type. CTBinary ContentType = "application/octet-stream" ) var ( // ErrConflict indicates that create or update of entity failed because // entity with same name already exists. ErrConflict = errors.New("entity already exists") // ErrFailedCreation indicates that entity creation failed. ErrFailedCreation = errors.New("failed to create entity") // ErrFailedUpdate indicates that entity update failed. ErrFailedUpdate = errors.New("failed to update entity") // ErrFailedPublish indicates that publishing message failed. ErrFailedPublish = errors.New("failed to publish message") // ErrFailedRead indicates that read messages failed. ErrFailedRead = errors.New("failed to read messages") // ErrFailedRemoval indicates that entity removal failed. ErrFailedRemoval = errors.New("failed to remove entity") // ErrFailedConnection indicates that connecting thing to channel failed. ErrFailedConnection = errors.New("failed to connect thing to channel") // ErrFailedDisconnect indicates that disconnecting thing from a channel failed. ErrFailedDisconnect = errors.New("failed to disconnect thing from channel") // ErrInvalidArgs indicates that invalid argument was passed. ErrInvalidArgs = errors.New("invalid argument passed") // ErrFetchFailed indicates that fetching of entity data failed. ErrFetchFailed = errors.New("failed to fetch entity") // ErrUnauthorized indicates unauthorized access. ErrUnauthorized = errors.New("unauthorized access") // ErrNotFound indicates that entity doesn't exist. ErrNotFound = errors.New("entity not found") // ErrInvalidContentType indicates that nonexistent message content type // was passed. ErrInvalidContentType = errors.New("Unknown Content Type") ) // ContentType represents all possible content types. type ContentType string var _ SDK = (*mfSDK)(nil) // User represents mainflux user its credentials. type User struct { Email string `json:"email"` Password string `json:"password"` } // Thing represents mainflux thing. type Thing struct { ID string `json:"id,omitempty"` Type string `json:"type"` Name string `json:"name,omitempty"` Key string `json:"key,omitempty"` Metadata string `json:"metadata,omitempty"` } // Channel represents mainflux channel. type Channel struct { ID string `json:"id,omitempty"` Name string `json:"name"` Things []Thing `json:"connected,omitempty"` Metadata string `json:"metadata,omitempty"` } // Message represents mainflux message. type Message struct { Channel string `json:"channel,omitempty"` Publisher string `json:"publisher,omitempty"` Protocol string `json:"protocol,omitempty"` Name string `json:"name,omitempty"` Unit string `json:"unit,omitempty"` Value *float64 `json:"value,omitempty"` StringValue *string `json:"stringValue,omitempty"` BoolValue *bool `json:"boolValue,omitempty"` DataValue *string `json:"dataValue,omitempty"` ValueSum *float64 `json:"valueSum,omitempty"` Time float64 `json:"time,omitempty"` UpdateTime float64 `json:"updateTime,omitempty"` Link string `json:"link,omitempty"` } // SDK contains Mainflux API. type SDK interface { // CreateUser registers mainflux user. CreateUser(user User) error // CreateToken receives credentials and returns user token. CreateToken(user User) (string, error) // CreateThing registers new thing and returns its id. CreateThing(thing Thing, token string) (string, error) // Things returns page of things. Things(token string, offset, limit uint64) ([]Thing, error) // Thing returns thing object by id. Thing(id, token string) (Thing, error) // UpdateThing updates existing thing. UpdateThing(thing Thing, token string) error // DeleteThing removes existing thing. DeleteThing(id, token string) error // ConnectThing connects thing to specified channel by id. ConnectThing(thingID, chanID, token string) error // DisconnectThing disconnect thing from specified channel by id. DisconnectThing(thingID, chanID, token string) error // CreateChannel creates new channel and returns its id. CreateChannel(channel Channel, token string) (string, error) // Channels returns page of channels. Channels(token string, offset, limit uint64) ([]Channel, error) // Channel returns channel data by id. Channel(id, token string) (Channel, error) // UpdateChannel updates existing channel. UpdateChannel(channel Channel, token string) error // DeleteChannel removes existing channel. DeleteChannel(id, token string) error // SendMessage send message to specified channel. SendMessage(chanID, msg, token string) error // ReadMessages read messagea of specified channel. ReadMessages(chanID, token string) ([]Message, error) // SetContentType sets message content type. SetContentType(ct ContentType) error // Version returns used mainflux version. Version() (string, error) } type mfSDK struct { baseURL string readerURL string readerPrefix string usersPrefix string thingsPrefix string httpAdapterPrefix string msgContentType ContentType client *http.Client } // Config contains sdk configuration parameters. type Config struct { BaseURL string ReaderURL string ReaderPrefix string UsersPrefix string ThingsPrefix string HTTPAdapterPrefix string MsgContentType ContentType TLSVerification bool } // NewSDK returns new mainflux SDK instance. func NewSDK(conf Config) SDK { return &mfSDK{ baseURL: conf.BaseURL, readerURL: conf.ReaderURL, readerPrefix: conf.ReaderPrefix, usersPrefix: conf.UsersPrefix, thingsPrefix: conf.ThingsPrefix, httpAdapterPrefix: conf.HTTPAdapterPrefix, msgContentType: conf.MsgContentType, client: &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: !conf.TLSVerification, }, }, }, } } func (sdk mfSDK) sendRequest(req *http.Request, token, contentType string) (*http.Response, error) { if token != "" { req.Header.Set("Authorization", token) } if contentType != "" { req.Header.Add("Content-Type", contentType) } return sdk.client.Do(req) } func createURL(baseURL, prefix, endpoint string) string { if prefix == "" { return fmt.Sprintf("%s/%s", baseURL, endpoint) } return fmt.Sprintf("%s/%s/%s", baseURL, prefix, endpoint) }