Делаем умный дом при помощи ASP.NET Core и Arduino

Во время карантина появилось много времени, которое захотелось потратить с пользой и закрепить свои знания полученные из разных сфер, из этого получился небольшой проект, который с лёгкостью может повторить любой разработчик.


image


Я студент, живу в общежитии. В комнате всегда проблемы с микро-климатом: то жарко, то холодно, то воздуха не хватает, а для комфортной работы и учёбы хотелось жить в нормальных условиях.


Итак, приступим.


Необходимый минимум


В углу завалялся старый, но достаточно мощный вентилятор.


image


Также есть Arduino Uno, оставшаяся со школьных времен.


image


Дополнительно купил датчик температуры и влажности, реле-модули. Для проекта принято решение арендовать VPS на Centos 7.


Разработка


Пишем скетч для Arduino. Он умеет отправлять данные с датчика и принимать информацию с компьютера.


  #include <Adafruit_GFX.h>
  #include <Adafruit_PCD8544.h>
  #include "DHT.h"
  #define DHTPIN 2 // номер пина, к которому подсоединен датчик
  int fanPin = 3;
  byte incomingByte;
  DHT dht(DHTPIN, DHT22);

  void setup() {
    pinMode(fanPin, OUTPUT);
    Serial.begin(9600);
    dht.begin();
  }

  void loop() {
    // Задержка 2 секунды между измерениями
    delay(2000);
    //Считываем влажность
    float h = dht.readHumidity();
    // Считываем температуру
    float t = dht.readTemperature();
    // Проверка удачно прошло ли считывание.
    if (isnan(h) || isnan(t)) {
      Serial.println("Не удается считать показания");
      return;
    } 

    Serial.print(" ");
    Serial.print( h );
    Serial.print(" ");
    Serial.print(t);
    Serial.print(" \n");

    if (Serial.available() > 0) {
      incomingByte = Serial.read();

      if(incomingByte == '0'){
        digitalWrite(fanPin, HIGH);
      }
      else if (incomingByte == '1'){
        digitalWrite(fanPin, LOW); 
      }
        Serial.print("I received: ");
        Serial.println(incomingByte, DEC);
    }
  }

После этого пишем небольшую программу на ASP.Net Сore которая принимает данные с Arduino и пишет их в базу данных. А также читает данные из БД, включает / отключает реле-модули через Arduino.


        public void Program()
        {
weatherContext db = new weatherContext();
            var serialPort = new SerialPort("COM3")
            {
                BaudRate = 9600,
                Parity = Parity.None,
                StopBits = StopBits.One,
                DataBits = 8,
                Handshake = Handshake.None
            };
            serialPort.Open();
            var reg = new Regex(@"[0-9]{2}\.[0-9]{2}\s[0-9]{2}\.[0-9]{2}");

            List<DeviceDTO> deviceDTOs = new List<DeviceDTO>();
            var userDevices = db.UserDevices.Where(d => d.UserId == 0);
            foreach (var userDevice in userDevices)
            {
                var device = db.Devices.Where(d => d.Id == userDevice.DeviceId).FirstOrDefault();
                if (device != null)
                {
                    DeviceDTO deviceDTO = new DeviceDTO()
                    {
                        Id = device.Id,
                        Status = device.Status,
                        Name = device.Name
                    };
                    deviceDTOs.Add(deviceDTO);
                }
            }
            while (true)
            {
                DeviceActivator(serialPort, deviceDTOs);
                string message = serialPort.ReadExisting();
                Console.WriteLine("message is: " + message);
                var match = reg.Match(message);
                IFormatProvider formatter = new NumberFormatInfo { NumberDecimalSeparator = "." };
                if (match.Success)
                {
                    string a = message.Substring(0, 5);
                    double humidity = double.Parse(a, formatter);
                    double temperature = double.Parse(message.Substring(6, 5), formatter);

                    List<MeteringWriteDTO> meterings = new List<MeteringWriteDTO>();
                    var meteringTemperature = new MeteringWriteDTO()
                    {
                        Id = meteringCount + 1,
                        Date = DateTime.UtcNow,
                        Value = temperature,
                        SensorId = 0,
                    };
                    meterings.Add(meteringTemperature);
                    var meteringHumidity = new MeteringWriteDTO()
                    {
                        Id = meteringCount + 1,
                        Date = DateTime.UtcNow,
                        Value = humidity,
                        SensorId = 1,
                    };
                    meterings.Add(meteringHumidity);
                    SetSecondMetering(meterings);
                    Console.WriteLine(message + DateTime.UtcNow + '\n');
                    System.Threading.Thread.Sleep(1000);
                }
                if (DateTime.UtcNow.Second == 0)
                {
                    SetMinuteMetering();
                }
                if (DateTime.UtcNow.Minute == 0 && DateTime.UtcNow.Second == 0)
                {
                    SetHourMetering();
                }
                if (DateTime.UtcNow.Hour == 0 && DateTime.UtcNow.Minute == 0 && DateTime.UtcNow.Second == 0)
                {
                    AddDay();
                }
            }
        }

На сервере развернулась небольшая база данных на PostgreSQL.


Таблица, куда пишутся данные с датчиков выглядит так:


image


Также есть таблица, хранящая информацию об устройствах:


image


И с этого момента началось создание клиент-серверного приложения на ASP.NET Core, которому предстояло попасть на сервер. Главная страница сейчас выглядит так:


image


Как видим, всё кратко и ёмко. Можно изменить статус устройства и посмотреть показания датчиков за определённый промежуток времени.


Итоги


Тестируем, что получилось:


image


Всё работает! Вентилятор запускается и выключается почти без задержек.


Планируется добавить графики с показаниями датчиков, систему авторизации, чтобы другие пользователи могли развернуть эту систему у себя дома. Можно легко настроить значения, при которых устройства будут включаться автоматически. Также количество датчиков и устройств предполагается увеличить.


Если заинтересовал проект, то могу сделать отдельные статьи по каждому шагу разработки.

Средняя зарплата в IT

120 000 ₽/мес.
Средняя зарплата по всем IT-специализациям на основании 9 284 анкет, за 1-ое пол. 2021 года Узнать свою зарплату
Реклама
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее

Комментарии 4

    +1
    Так а где Asp.Net Core? Я вижу только консольное приложение.
    Где код? Линка на гитхаб?

    Если сайт хостится на впс-ке, то на чем крутится сам контроллер?

     var userDevices = db.UserDevices.Where(d => d.UserId == 0);
     foreach (var userDevice in userDevices)
     {
            var device = db.Devices.Where(d => d.Id == userDevice.DeviceId).FirstOrDefault();
      }
    

    Navigation properties для слабаков. N+1 — наше всё.
      0
      Спасибо за замечание. В первой версии статьи кода не было вообще. Т.к. статья лежала на одобрении примерно неделю-полторы код сильно изменился, появились графики, провёл рефакторинг)
      Для меня важно было передать смысл того, что это может сделать каждый, но раз такие вопросы пошли, могу и на гит залить. Статью отредачу, как только появятся силы.

      Насчёт впс и контроллера. Схема такая: сайт на сервере, а консольная прога на C# работает на компьютере локально, компьютер соединён с платой ардуино. Прога общается с БД. Сегодня как раз заказал плату Arduino с WIFI, чтобы лишиться главного костыля системы — обязательно должен работать ПК со всей этой системой. Теперь плата будет общаться с VPS в обход C# на локалке.
      0
      Прикольно!

      Но студенческий код ты зря выложил, щас набросятся :D
        0
        Спасибо! Да отредачу, залью на гит.

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое