Skip to content

A smart home system with Arduino, InfluxDB, Go, gRPC, and Ionic.

License

Notifications You must be signed in to change notification settings

david-slatinek/ax87

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Project logo

Table of Contents

About

A smart home system with Arduino, InfluxDB, Go, gRPC, and Ionic.

The project consists of 4 main components:

  • Data capture from the sensors using Arduino.
  • Database for data storage.
  • API for storing and retrieving data.
  • Mobile app for displaying the values.
Project infrastructure
Project infrastructure.

Arduino

Arduino

Arduino is responsible for getting the data from the sensors for the following:

  • Carbon monoxide.
  • Air quality.
  • Raindrops.
  • Soil moisture.

After that, it uploads data to the API by calling an appropriate gRPC method:

conn, err := grpc.Dial("address", grpc.WithTransportCredentials(tlsCred))
client := pb.NewRequestClient(conn)

client.Add(context.Background(), &pb.Data{
    DataType:  pb.DataType(dataType),
    Value:     value,
    Timestamp: timestamppb.New(time.Now()),
})

Arduino wiring
Sensors schematic.

More circuit design images can be seen here.

API

Go Shell Script openssl InfluxDB redis AWS Amazon EC2

The API was made with the language Go, gRPC framework and is hosted by AWS EC2. For the database, we chose InfluxDB, which is hosted by the InfluxDB Cloud.

Since we have 2 servers for API hosting, we also added AWS ELB for distributing network traffic.

Data is stored in a single bucket with four different measurements:

  • CARBON_MONOXIDE.
  • AIR_QUALITY.
  • RAINDROPS.
  • SOIL_MOISTURE.

Each measurement has three fields: value, i.e. the sensor's recorded value; _time, i.e. when the value was taken; and category, with it being in the following range:

  • For CARBON_MONOXIDE it is [1, 7], with 1 being the best.
  • For AIR_QUALITY it is [1, 6], with 1 being the best.
  • For RAINDROPS it is [1, 4], with 1 indicating no or little rain.
  • For SOIL_MOISTURE it is [0, 100]%, with 0 indicating no soil moisture.

To speed up queries, we used Redis as an in-memory cache, which stores the latest added data and is hosted by Amazon ElastiCache.

We also added support for unit testing, with the appropriate files having the _test.go suffix.

Lastly, we added support for mutual TLS with the help of OpenSSL.

The gRPC service (.proto file) can be seen here.

func (server *Server) Latest(_ context.Context, request *pb.DataRequest) 
(*pb.DataWithCategory, error) {
	if request == nil {
		return nil, status.Error(codes.InvalidArgument, "request can't be nil")
	}

	var latest *model.DataResponse
	var ok = false

	if server.cache != nil {
		value, err := server.cache.Get(request.DataType.String())

		if err != nil && server.Development {
			log.Printf("Error with cache get, error: %v", err)
		} else {
			if err := json.Unmarshal([]byte(value), &latest); 
			err != nil && server.Development {
				log.Printf("Error with json.Unmarshal, error: %v", err)
			} else if err != redis.Nil && value != "" {
				ok = true
			}
		}
	}

	if !ok {
		var err error

		latest, err = server.DBService.Latest(request.GetDataType().String())
		if err != nil {
			return nil, status.Error(codes.NotFound, err.Error())
		}

		if err = server.AddToCache(latest); err != nil && server.Development {
			log.Printf("Error with cache set, error: %v", err)
		}
	}

	return latest.Convert(), nil
}

Method to get the latest record.

App

Ionic React TypeScript

The mobile app was made with Ionic, React, and TypeScript. The main app functionality is getting data from the API and displaying it.

The app features the latest, median, maximum, minimum, and all today's values.

Main screen 1 Main screen 2
Screen for displaying all today's values Screen for choosing measurement type