Статьи

Raspberry PI + Nancy + (необязательный MySQL) = создать миниатюрную встроенную службу на основе HTTP

Вступление

В этой статье мы увидим, как настроить и использовать Nancy (это легковесная, простая церемония и инфраструктура для построения HTTP-сервисов на .Net и Mono) в Raspberry PI.

Основная идея использования Nancy для создания сервисов на основе HTTP, а не использования Web API или другого механизма, заключается в простоте Nancy.

Как говорят создатели Nancy, это просто работает, и вам не нужно беспокоиться об изменениях конфигурации и т. Д. Нет никакой нагрузки при настройке Nancy и размещении нашего приложения в Linux.

Если вы новичок в Нэнси, настоятельно рекомендуется иметь некоторое понимание того же. Вы можете прочитать по ссылке ниже.

https://github.com/NancyFx/Nancy/wiki/Documentation

В этой статье используется образец базы данных MySQL по ссылке ниже.

http://www.mysqltutorial.org/mysql-sample-database.aspx

Он имеет базовый набор моделей данных реального мира, с помощью которых мы будем разрабатывать простой и элегантный сервис на основе HTTP с использованием Nancy и размещать его на Raspberry PI.

Наша цель — сначала настроить необходимое программное обеспечение — MySQL, Nancy на Raspberry PI. Затем мы создадим простое приложение Nancy, чтобы сделать данные MySQL доступными для внешнего мира через службу Nancy HTTP. Когда дело доходит до размещения нашего приложения, чтобы упростить задачу, мы будем размещать наше демонстрационное приложение на консоли.

Позже мы будем тестировать то же самое, сделав HTTP-запрос с соответствующим типом содержимого, установленным для отображения данных в формате JSON или XML.

Первое, что мы делаем, это устанавливаем сервер MySQL на Raspberry PI. Просто запустите указанную ниже команду на консоли Linux.

sudo apt-get install mysql-server

Это займет некоторое время, чтобы загрузить и установить. Но следует помнить одну вещь: когда вас просят ввести «Новый пароль для MySQL для« корневого »пользователя», введите пароль, а затем подтвердите его.

Далее мы будем соединять mysql с пользователем root, выполнив следующую команду в оболочке.

mysql -u root -p

Вы можете выполнить файл сценария для создания базы данных и загрузки образцов данных, выполнив следующую команду

mysql> source file_name
or
mysql> \. file_name

Ниже приведен снимок, на котором вы видите, я запускаю файл скрипта из папки «/ home / pi / webservices / NancySample1 /» .

Давайте посмотрим на настройку Нэнси. Убедитесь, что вы установили Mono, как это требуется для запуска Nancy. Вы можете запустить следующую команду, чтобы установить Mono.

sudo apt-get install mono-complete

Мы будем загружать и компилировать код Нэнси на Raspberry PI. Ниже приведены шаги, которые вы должны будете выполнить. Примечание. Я только что повторно использовал команды из приведенной ниже документации. Не стесняйтесь заглянуть, если вы хотите узнать больше.

https://github.com/NancyFx/Nancy/wiki/Running-Nancy-on-your-Raspberry-Pi

mkdir /home/pi/code (or any other directory you prefer)
cd /home/pi/code
sudo apt-get install git ruby rake
sudo gem install albacore --version "1.0.0.rc2"
git clone https://github.com/NancyFx/Nancy.git
cd Nancy
rake mono

Вы обязательно столкнетесь с ошибкой при выполнении последней команды «rank mono». Как сказано в документации «Gem albacore версии 0.3.5 содержит ошибку зависимости с rubyzip». Пожалуйста, следуйте инструкциям ниже, чтобы установить правильную версию albacore.

sudo aptitude install ruby1.9.1-dev
cd ~/code/
git clone https://github.com/Albacore/albacore.git
cd albacore
gem build albacore.gemspec
sudo gem install albacore-2.3.1.gem

Вся установка займет некоторое время. Пожалуйста, имейте некоторое терпение, чтобы установить эти вещи на вашем PI.

Еще несколько вещей, чтобы начать кодирование службы на основе HTTP с помощью Nancy.

  1. Убедитесь, что служба MySQL запущена, выполнив следующую команду.
sudo service mysql restart
  1. Это не обязательно. Скажите, если вы заинтересованы в удаленном доступе к базе данных MySQL, установленной в Raspberry PI, выполните следующие действия.

Вы должны отредактировать файл конфигурации MySQL и изменить адрес привязки с 127.0.0.1 на 0.0.0.0.

Запустите команду ниже, чтобы сделать то же самое.

sudo nano /etc/mysql/my.cnf

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

sudo service mysql restart
  1. Следующим шагом является предоставление доступа к удаленному соединению. Для этого вам нужно создать пользователя, а затем явно предоставить необходимые разрешения для того же. Вы должны войти в MySQL от имени пользователя root (mysql -p -u root) и выполнить приведенные ниже действия, указав имя базы данных, имя пользователя и пароль.
CREATE USER 'MY_USERNAME'@'localhost' IDENTIFIED BY 'MY_PASSWORD';




GRANT ALL PRIVILEGES ON MY_DATABASE_NAME.* TO 'MY_USERNAME'@'%' IDENTIFIED BY 'MY_PASSWORD';
           flush privileges;

Настало время написать самую захватывающую вещь. Это служба HTTP на основе Нэнси. Я использую Visual Studio, а точнее VS 2010 для написания этого примера приложения.

Создайте консольное приложение и установите пакет NuGet для самостоятельного размещения HTTP-сервисов на основе Nancy.

PM> Install-Package Nancy.Hosting.Self
Attempting to resolve dependency 'Nancy (≥ 0.23.2)'.
Installing 'Nancy 0.23.2'.
Successfully installed 'Nancy 0.23.2'.
Installing 'Nancy.Hosting.Self 0.23.2'.
Successfully installed 'Nancy.Hosting.Self 0.23.2'.
Adding 'Nancy 0.23.2' to NancySample1.
Successfully added 'Nancy 0.23.2' to NancySample1.
Adding 'Nancy.Hosting.Self 0.23.2' to NancySample1.
Successfully added 'Nancy.Hosting.Self 0.23.2' to NancySample1. 

Следующим шагом является установка MySQL.Data, который является драйвером ADO.NET для MySQL.

PM> Install-Package MySQL.Data

Давайте запустим наш пример приложения Nancy, создав нижеупомянутые объекты.

public class Customer
{
        public int CustomerNumber { get; set; }
        public string CustomerName { get; set; }
        public string ContactLastName { get; set; }
        public string ContactFirstName { get; set; }
        public string Phone { get; set; }
        public string AddressLine1 { get; set; }
        public string AddressLine2 { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }
        public double CreditLimit { get; set; }
}

public class Employee
{
        public int EmployeeNumber { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string Extension { get; set; }
        public string Email { get; set; }
        public string OfficeCode { get; set; }
        public string ReportTo { get; set; }
        public string JobTitle { get; set; }
}

Создать службу на основе HTTP с помощью Nancy очень просто, если ваш класс выходит из NancyModule. Ниже приведен фрагмент кода, где вы можете увидеть, как настраивается код для ответа на HTTP-запрос на получение всей информации о клиенте или информации о клиенте по Id и т. Д. 

public class Program : NancyModule
{
           public Program()
           {
               GetCustomers();
               GetCustomerById();
               GetEmployees();
           }

           void GetCustomers()
           {
               // Get all customers
               Get["/customer"] = _ =>
               {
                   var customerRepository = new CustomerRepository();
                   var customerCollection = 
                       customerRepository.GetCustomerInfo("select *from customers");
                   return Negotiate
                        .WithStatusCode(HttpStatusCode.OK)
                        .WithModel(customerCollection.ToArray());
               };    
           }

           void GetCustomerById()
           {
               Get["/customer/{id}"] = parameters =>
               {
                   int id = parameters.id;
                   var customerRepository = new CustomerRepository();
                   var customerCollection = customerRepository.GetCustomerInfo(
                       string.Format("select *from customers where customerNumber={0}", id));
                   return Negotiate
                       .WithStatusCode(HttpStatusCode.OK)
                       .WithModel(customerCollection);
               };
           }

           void GetEmployees()
           {
               // Get all employees
               Get["/employee"] = _ =>
               {
                   var employeeRepository = new EmployeeRepository();
                   var employeeCollection = 
                       employeeRepository.GetEmployeeInfo("select *from employees");
                   return Negotiate
                        .WithStatusCode(HttpStatusCode.OK)
                        .WithModel(employeeCollection.ToArray());
               };    
           }
}

Вот фрагмент кода для размещения нашего примера приложения Nancy на консоли.

static void Main()
{
          Console.Write("Starting server...");
          var server = new Nancy.Hosting.Self.NancyHost(new Uri("http://localhost:8282"));
          server.Start();
          Console.WriteLine("started!");
          Console.WriteLine("press any key to exit");
          Console.Read();
}

Ниже приведен фрагмент кода для репозитория клиентов, который не более чем возвращает набор информации о клиентах, основанный на конкретном SQL. Код не требует пояснений; мы будем открывать соединение MySQL со строкой соединения, определенной в конфигурации приложения. Затем выполните команду SQL и используйте средство чтения данных MySQL, чтобы просмотреть и прочитать информацию о клиенте.

public class CustomerRepository
{
        public List<Customer> GetCustomerInfo(string sql)
        {
            string sConnectionString = ConfigurationManager.AppSettings["DbConnectionString"];
            var customerCollection = new List<Customer>();

            try
            {
                using (var dbConnection = new MySqlConnection(sConnectionString))
                {
                    dbConnection.Open();
                    var dbCommand = new MySqlCommand(sql, dbConnection);
                    var dbReader = dbCommand.ExecuteReader();

                    while (dbReader.Read())
                    {
                        customerCollection.Add(new Customer
                        {
                            CustomerNumber = dbReader.GetInt32("customerNumber"),
                            CustomerName = dbReader["customerName"] is DBNull ? "" : 
                                    dbReader.GetString("customerName"),
                            ContactFirstName = dbReader["contactFirstName"] is DBNull ? "" : 
                                    dbReader.GetString("contactFirstName"),
                            ContactLastName = dbReader["contactLastName"] is DBNull ? "" :
                                    dbReader.GetString("contactLastName"),
                            AddressLine1 = dbReader["addressLine1"] is DBNull ? "" :
                                 dbReader.GetString("addressLine1"),
                            AddressLine2 = dbReader["addressLine2"] is DBNull ? "" :
                                 dbReader.GetString("addressLine2"),
                            City = dbReader["city"] is DBNull ? "" : 
                                 dbReader.GetString("city"),
                            State = dbReader["state"] is DBNull ? "" :
                                 dbReader.GetString("state"),
                            PostalCode = dbReader["postalCode"] is DBNull ? "" : 
                                 dbReader.GetString("postalCode"),
                            Country = dbReader["country"] is DBNull ? "" : 
                                 dbReader.GetString("country"),
                        });
                    }
                }
            }
            catch (MySqlException ex)
            {
                Console.WriteLine("Error: {0}", ex);
                throw;
            }

            return customerCollection;
        } 
} 

Ниже приведен фрагмент кода для репозитория сотрудников. 

public class EmployeeRepository
{
        public List<Employee> GetEmployeeInfo(string sql)
        {
            string sConnectionString = ConfigurationManager.AppSettings["DbConnectionString"];
            var employeeCollection = new List<Employee>();

            try
            {
                using (var dbConnection = new MySqlConnection(sConnectionString))
                {
                    dbConnection.Open();
                    var dbCommand = new MySqlCommand(sql, dbConnection);
                    var dbReader = dbCommand.ExecuteReader();

                    while (dbReader.Read())
                    {
                        employeeCollection.Add(new Employee
                        {
                            EmployeeNumber = dbReader.GetInt32("employeeNumber"),
                            FirstName = 
                               dbReader["firstName"] is DBNull ? "" : dbReader.GetString("firstName"),
                            LastName = 
                               dbReader["lastName"] is DBNull ? "" : dbReader.GetString("lastName"),
                            Email = dbReader["email"] is DBNull ? "" : dbReader.GetString("email"),
                            Extension = 
                               dbReader["extension"] is DBNull ? "" : dbReader.GetString("extension"),
                            ReportTo = 
                               dbReader["reportsTo"] is DBNull ? "" : dbReader.GetString("reportsTo"),
                            JobTitle = 
                               dbReader["jobTitle"] is DBNull ? "" : dbReader.GetString("jobTitle")
                        });
                    }
                }
            }
            catch (MySqlException ex)
            {
                Console.WriteLine("Error: {0}", ex);
                throw;
            }

            return employeeCollection;
        }
} 

Теперь пришло время запустить исполняемые файлы приложения или приложения на Raspberry PI. Вот что вы можете сделать. Скомпилируйте приложение со своего настольного компьютера / ноутбука, а затем используйте FTP-клиент, например FileZilla, для установки FTP-соединения с вашим PI. После успешного подключения вы можете скопировать все необходимые исполняемые файлы.

Вы можете использовать приложение Putty или, если вы уже подключили Raspberry PI к монитору с помощью клавиатуры и мыши, вы можете перейти к исполняемому каталогу и просто запустить консольное приложение Nancy изнутри оболочки, выполнив следующую команду.

mono NancySample1.exe

Теперь давайте поищем расширение chrome « DHC — REST / HTTP API Client » и установим его. Это отличный инструмент для создания HTTP-запроса.

Ниже приведен снимок, показывающий, как мы собираемся сделать простой HTTP-запрос с типом контента, установленным в «application / json».

Примечание. Обязательно запишите IP-адрес вашего Raspberry PI, выполнив команду «ifconfig» из оболочки. 

Я слышал о Нэнси несколько месяцев назад. Но я никогда не думал, что буду использовать в экспериментальных проектах Raspberry PI. Было очень интересно создать простой сервис в кратчайшие сроки. Я действительно ценю простоту Нэнси.