Перейти к содержанию

Particle Photon


Рекомендуемые сообщения

Particle Photon

Микроконтроллеры ESP32 и ESP8266 наделали много шума в среде радиолюбителей. Основное их преимущество - поддержка интернет соединения посредством Wi-Fi.

Но ESP не единственные "девборды" с Wi-Fi и одна из множества плат разработки с Wi-Fi попала ко мне на обзор.

Итак, Particle Photon - плата прототипирования (терпеть не могу это слово, не правильное оно какое-то, но аналога в русском языке нет) с Wi-Fi, но со своими особенностями предоставлена на обзор магазином DFRobot.

photon_pin_markings_1400.png?timestamp=1

Имеет следующие параметры:

  • Broadcom BCM43362 Wi-Fi chip 802.11b/g/n Wi-Fi Datasheet
  • STM32F205RGY6 120Mhz ARM Cortex M3 1MB flash, 128KB RAM Datasheet
  • On-board RGB status LED
  • 18 Mixed-signal GPIO and advanced peripherals
  • Open source design
  • Real-time operating system (FreeRTOS)
  • Soft AP setup

Диаграмма (Block Diagram):

photon-block-diagram.png?timestamp=15414

GPIO порты:

  • 18 цифровых I/O
  • 8 АЦП
  • 2 ЦАП
  • 2 SPI
  • 1 I2S
  • 1 CAN
  • 1 USB 
  • 9 PWM
  • 1 JTAG

Распиновка представлена на следующих изображениях:

photon-pinout1.png?timestamp=15414268194

photon-pinout2.png?timestamp=15414268194

И выводы микроконтроллера, к которым нет прямого подключения, но ими можно управлять программно.

photon-pinout3.png?timestamp=15414268194

И еще один вариант распиновки (распиновка та же, изображение нагляднее):

particle-photon-headers_pinout.png?times

Особенностью "фотона" (как и всех устройств Particle) является связь через облако Particle. Даже программирование осуществляется через облако.

Товарищи из Particle серьезно подошли к делу и создали несколько инструментов для работы со своими устройствами (не только с "фотоном", но и с остальными).

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

По большому счету приложение не приносит большой пользы. Через него можно по управлять "фотоном", очень забавно это реализовано. Но запрограммировать не получится (что странно, ведь программирование происходит через Web сервис и реализовать его в приложении не сложно). Так же у меня не получилось и настроить "фотон" через приложение. Вообще с настройкой возникли некоторые сложности не только через мобильное приложение, но и другими способами ("фотон" упорно не хотел настраиваться, но возможно это "особенности" моего провайдера). Так что мобильное приложения я буду использовать только для проверки статуса "фотона" и продемонстрирую как через приложение управлять "фотоном".

Второй инструмент для работы с "фотоном" - CLI (command-line interface), позволяет работать с "фотоном" через командную строку.

Я так же пытался настроить "фотон" через командную строку, но неудачно. поэтому я потерял интерес к командной строке и упоминать её далее я не буду.

Здесь должна была быть пара скриншотов CLI, но я на днях сбросил ОС на своем ноутбуке до состояния "только купил" и все установленные программы конечно же удалились. Сейчас же попытка установить CLI привела к тому, что якобы всё установилось, но...

1212121.png?timestamp=1541426819410

Эта надпись висит весь день, но плагины так и не устанавливаются. Хотя в первый раз всё установилось и заработало сразу.

Третий инструмент - Particle Dev, IDE для ПК.

Image_1.png?timestamp=1541426819410

Настроить "фотон" через компьютерную программу у меня снова не получилось. Программа опознала что "фотон" подключен через USB (драйвера кстати, установились самостоятельно и без проблем), но дальше этого обнаружения дело не пошло. Кстати CLI так же увидел "фотон" через USB, но не смог...

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

И, наконец. четвертый инструмент - Web IDE. Непосредственно на сайте производителя есть он-лайн редактор кода с подсветкой синтаксиса, выбором библиотек и консолью. Отсюда же можно отправить прошивку на устройство, обновить версию программного обеспечения "фотона" и многое другое.

Image_2.png?timestamp=1541426819410

Мой выбор пал на Web IDE, потому что этот способ работы с "фотоном" оказался самым стабильным.

Настроить фотон из Web IDE нет возможности, но предусмотрена другая возможность настроить "фотон" при помощи браузера. Но при этом компьютер должен иметь возможность подключаться к беспроводным сетям (короче говоря должен иметь wi-fi адаптер). И хотя этот способ срабатывал у меня один раз из пятидесяти (утрирую), в отличии от всех других способов он все же сработал.

Для того, чтобы настроить "фотон" при помощи браузера, необходимо первым делом залогиниться на сайте, затем перейти по адресу https://setup.particle.io/ и выбрать "Photon/P Series", откроется страница с дальнейшими указаниями - подключить питание к "фотону" и ввести его в режим настройки (светодиод должен моргать синим цветом). Режим настройки меня слегка удивил. В инструкции сказано "нажмите кнопку setup на 3 секунды для перевода "фотона" в режим настройки", но иногда это не срабатывает. Опытным путем я установил, что в этом случае необходимо многократно нажать кнопку setup. Итак, "фотон" переведен в режим настройки, жмем "next" и затем "CONTINUE WITH LOCAL FILE", сохраните html файл и откройте его в браузере. Здесь начинаются чудеса. Во первых, предупрежу, что скачанный html файл вы можете использовать только в течении 60 минут.  

Во-вторых, не торопитесь подключаться к точке доступа, созданной "фотоном", открыть скачанный html файл надо до подключения к "фотону", затем подключиться к точке доступа, созданной фотоном.

Image_4.png?timestamp=1541426819410

Затем необходимо настроить к какой точке доступа "фотон" должен подключаться.

Image_6.png?timestamp=1541426819411

Я использую интернет без пароля. И настройка выдает ошибку, мол все поля должны быть заполнены. 

Image_7.png?timestamp=1541426819411

Поэтому ставим галочку "The network has a hidden SSID", в поле "SSID (the name of your Wi-Fi network)" вводим имя сети, в выпадающем списке "Security type" я выбираю "open".

Image_8.png?timestamp=1541426819411

Жмем большую синюю кнопку..

Image_9.png?timestamp=1541426819411

Если на "фотоне" RGB светодиод моргает "циановым" - настройка успешна, если синим или зеленым - нет. Затем необходимо подключиться к основной точке доступа Wi-Fi и попадаем на страницу, где можно задать имя своему "фотону".

Image_10.png?timestamp=1541426819411

На этом настройка окончена. Переходим в Web IDE.

Если нажать на значок напоминающий прицел, выпадет меню, в котором можно выбрать необходимое для работы устройство. Оно у меня в списке одно. Так же в правом нижнем углу можно увидеть имя устройства и "циановый" кружок - "фотон" подключен к облаку Particle.

Image_11.png?timestamp=1541426819411

Символ в виде ленточки открывает список библиотек. Список библиотек выводится на экран по 10 библиотек. Так же есть поиск по названию библиотеки.

Image_12.png?timestamp=1541426819411

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

Image_16.png?timestamp=1541426819412

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

Image_13.png?timestamp=1541426819412

Угловые скобки <> ведут к меню файлов. Если вам необходимо создать новый файл, открыть существующий или сохранить редактируемый - вам сюда.

Image_14.png?timestamp=1541426819412

В общем разобраться в интерфейсе не сложно даже новичку.

Теперь о самом интересном - о программировании "фотона".

Сразу приведу ссылку на справку по языку программирования: https://docs.particle.io/reference/device-os/firmware/photon/ 

Замечу, что язык программирования "фотона" очень похож на язык программирования ардуино. Так же используются функции setup и loop, так же настраиваются порты GPIO, работа с UART, SPI и I2C почти не отличается от ардуино, кроме нюансов. Эти нюансы очень важны, поэтому без этой справки не обойтись.

Сейчас, в этом обзоре, я не могу охватить всю справку по фотону, там более 300 страниц информации из расчета размера листа А4.

Image_17(1).png?timestamp=1541426819412

Поэтому постараюсь вкратце.

Я уже писал про некоторые нюансы. Вот пример одного из них:

 

  • When using INPUT_PULLDOWN make sure a high level signal does not exceed 3.3V. При использовании INPUT_PULLDOWN убедитесь, что сигнал высокого уровня не превышает 3,3 В.
  • INPUT_PULLUP does not work as expected on TX on the P1, Electron, and E Series and should not be used. NPUT_PULLUP не работает так, как ожидалось, в TX на сериях P1, Electron и E и не следует использовать
  • INPUT_PULLDOWN does not work as expected on D0 and D1 on the P1 because the P1 module has hardware pull-up resistors on these pins. NPUT_PULLDOWN работает не так, как ожидалось, на D0 и D1 на P1, потому что модуль P1 имеет аппаратные подтягивающие резисторы на этих контактах
  • Also beware when using pins D3, D5, D6, and D7 as OUTPUT controlling external devices.
  • After reset, these pins will be briefly taken over for JTAG/SWD, before being restored to the default high-impedance INPUT state during boot. Также будьте осторожны при использовании контактов D3, D5, D6 и D7 в качестве OUTPUT, управляющих внешними устройствами. После сброса эти контакты будут кратко переведены для JTAG / SWD, прежде чем будут восстановлены состояние INPUT
  • с высоким полным сопротивлением во время загрузки.
  • D3, D5, and D7 are pulled high with a pull-up
  • D6 is pulled low with a pull-down
  • D4 is left floating

В общем таких нюансов много и все их в одну статью не вместить. Здесь надо целую книгу писать.

Но кое о чем особенном я заострю внимание. Устройства Particle работают через облако не только для загрузки прошивки. Через облако можно передавать переменные от "фотона" и взаимодейтсвовать с "фотоном" посредством облачных функций. Рассмотрим примеры.

int analogvalue = 0;

double tempC = 0;

char *message = "my name is particle";

String aString;



void setup()

{

  // variable name max length is 12 characters long

  Particle.variable("analogvalue", analogvalue);

  Particle.variable("temp", tempC);

  if (Particle.variable("mess", message)==false)

  {

      // variable not registered!

  }

  Particle.variable("mess2", aString);



  pinMode(A0, INPUT);

}



void loop()

{

  // Read the analog value of the sensor (TMP36)

  analogvalue = analogRead(A0);

  //Convert the reading into degree celcius

  tempC = (((analogvalue * 3.3)/4095) - 0.5) * 100;

  delay(200);

}

В данном примере показана работа с облачными переменными. К сожалению эти переменные передаются только в одну сторону - от "фотона" в облако. Удаленно прочитать эти переменные можно через мобильное приложение или через браузер. 

Скриншот мобильного приложения:

Screenshot_20181102-183038_Particle.jpg?

Что бы прочитать значение переменной через браузер необходимо ввести в адресную строку адрес вида https://api.particle.io/v1/devices/3a002c000c47353136383731/analogvalue?access_token=481afe0e8625fe50f61c6a1e789f968d4a27fd2c , где 

  • 3a002c000c47353136383731 - Device ID устройства,
  • 481afe0e8625fe50f61c6a1e789f968d4a27fd2c - токен доступа
  • analogvalue - имя переменной.

В результате облако передает данные в формате JSON.

{"cmd":"VarReturn",

"name":"analogvalue",

"result":1367,

"coreInfo":{"last_app":"",

  "last_heard":"2018-11-02T13:27:40.573Z",

  "connected":true,

  "last_handshake_at":"2018-11-02T13:27:40.271Z",

  "deviceID":"3a002c000c47353136383731",

  "product_id":6}

}

К сожалению через браузер можно получить одну переменную, а не все разом, как через приложение. Но, если убрать имя переменной из адресной строки ( https://api.particle.io/v1/devices/3a002c000c47353136383731/?access_token=22e4a7a7d63b534b1504b05fd6ee4bb8b18665b2 ), то можно узнать список всех переменных и их типы данных. И, если вы заметили. там же упоминаются некие функции.

{"id":"3a002c000c47353136383731",

"name":"giant-ninja",

"last_app":null,

"last_ip_address":"62.143.162.99",

"last_heard":"2018-1102T13:32:06.711Z",

"product_id":6,

"connected":true,

"platform_id":6,

"cellular":false,

"notes":null,

"status":"normal",

"serial_number":"PH-161114-9YF6-0",

"current_build_target":"0.7.0",

"system_firmware_version":"0.7.0",

"default_build_target":"0.7.0",

"variables":{"analogvalue":"int32",

  "temp":"double",

  "mess":"string",

  "mess2":"string"},

"functions":[]}

Облачные функции позволяют взаимодействовать с "фотоном". Рассмотрим код из примера.

int brewCoffee(String command);



void setup()

{

  // register the cloud function

  Particle.function("brew", brewCoffee);

}



void loop()

{

  // this loops forever

}



// this function automagically gets called upon a matching POST request

int brewCoffee(String command)

{

  // look for the matching argument "coffee" <-- max of 64 characters long

  if(command == "coffee")

  {

    // some example functions you might have

    //activateWaterHeater();

    //activateWaterPump();

    return 1;

  }

  else return -1;

}

Функция brewCoffee объявляется до функции setup, в функции setup привязывается к облаку и получает имя "brew", которое используется в облаке. Сама функция размещена после loop, а в loop ничего нет. 

Функция принимает в качестве аргумента строку, в данном случае если строка "coffee", то функция возвращает 1, если что-либо иное - возвращает -1. То есть у функции есть ограничения: агрумент должен быть один, иметь тип строки, функция должна возвращать целое число. Скриншот из приложения:

Screenshot_20181102-192329_Particle.jpg?

Screenshot_20181102-192413_Particle.jpg?

Screenshot_20181102-192420_Particle.jpg?

Вызов адреса https://api.particle.io/v1/devices/3a002c000c47353136383731/?access_token=22e4a7a7d63b534b1504b05fd6ee4bb8b18665b2 возвращает следующее:

{"id":"3a002c000c47353136383731",

"name":"giant-ninja",

"last_app":null

,"last_ip_address":"62.143.162.99"

,"last_heard":"2018-11-02T13:52:53.692Z",

"product_id":6,

"connected":true,

"platform_id":6,

"cellular":false,

"notes":null,

"status":"normal",

"serial_number":"PH-161114-9YF6-0",

"current_build_target":"0.7.0",

"system_firmware_version":"0.7.0",

"default_build_target":"0.7.0",

"variables":{},

"functions":["brew"]}

В самом конце видно упоминание функции brew, но больше ничего через браузер сделать не получается (либо я настолько глуп что не разобрался).

Еще одно фишка "фотона" - События.

Рассмотрим код из примера.

// -----------------------------------------

// Publish and Dashboard with Photoresistors

// -----------------------------------------

// This app will publish an event when the beam of light between the LED and the photoresistor is broken.

// It will publish a different event when the light is intact again.



// Just like before, we're going to start by declaring which pins everything is plugged into.



int led = D0; // This is where your LED is plugged in. The other side goes to a resistor connected to GND.

int boardLed = D7; // This is the LED that is already on your device.

// On the Core, it's the LED in the upper right hand corner.

// On the Photon, it's next to the D7 pin.



int photoresistor = A0; // This is where your photoresistor is plugged in. The other side goes to the "power" pin (below).



int power = A5; // This is the other end of your photoresistor. The other side is plugged into the "photoresistor" pin (above).



// The following values get set up when your device boots up and calibrates:

int intactValue; // This is the average value that the photoresistor reads when the beam is intact.

int brokenValue; // This is the average value that the photoresistor reads when the beam is broken.

int beamThreshold; // This is a value halfway between ledOnValue and ledOffValue, above which we will assume the led is on and below which we will assume it is off.



bool beamBroken = false; // This flag will be used to mark if we have a new status or now. We will use it in the loop.



// We start with the setup function.



void setup() {

  // This part is mostly the same:

  pinMode(led,OUTPUT); // Our LED pin is output (lighting up the LED)

  pinMode(boardLed,OUTPUT); // Our on-board LED is output as well

  pinMode(photoresistor,INPUT);  // Our photoresistor pin is input (reading the photoresistor)

  pinMode(power,OUTPUT); // The pin powering the photoresistor is output (sending out consistent power)



  // Next, write the power of the photoresistor to be the maximum possible, which is 4095 in analog.

  digitalWrite(power,HIGH);



  // Since everyone sets up their leds differently, we are also going to start by calibrating our photoresistor.

  // This one is going to require some input from the user!



  // First, the D7 LED will go on to tell you to put your hand in front of the beam.

  digitalWrite(boardLed,HIGH);

  delay(2000);



  // Then, the D7 LED will go off and the LED will turn on.

  digitalWrite(boardLed,LOW);

  digitalWrite(led,HIGH);

  delay(500);



  // Now we'll take some readings...

  int on_1 = analogRead(photoresistor); // read photoresistor

  delay(200); // wait 200 milliseconds

  int on_2 = analogRead(photoresistor); // read photoresistor

  delay(300); // wait 300 milliseconds



  // Now flash to let us know that you've taken the readings...

  digitalWrite(boardLed,HIGH);

  delay(100);

  digitalWrite(boardLed,LOW);

  delay(100);

  digitalWrite(boardLed,HIGH);

  delay(100);

  digitalWrite(boardLed,LOW);

  delay(100);



  // Now the D7 LED will go on to tell you to remove your hand...

  digitalWrite(boardLed,HIGH);

  delay(2000);



  // The D7 LED will turn off...

  digitalWrite(boardLed,LOW);



  // ...And we will take two more readings.

  int off_1 = analogRead(photoresistor); // read photoresistor

  delay(200); // wait 200 milliseconds

  int off_2 = analogRead(photoresistor); // read photoresistor

  delay(1000); // wait 1 second



  // Now flash the D7 LED on and off three times to let us know that we're ready to go!

  digitalWrite(boardLed,HIGH);

  delay(100);

  digitalWrite(boardLed,LOW);

  delay(100);

  digitalWrite(boardLed,HIGH);

  delay(100);

  digitalWrite(boardLed,LOW);

  delay(100);

  digitalWrite(boardLed,HIGH);

  delay(100);

  digitalWrite(boardLed,LOW);





  // Now we average the "on" and "off" values to get an idea of what the resistance will be when the LED is on and off

  intactValue = (on_1+on_2)/2;

  brokenValue = (off_1+off_2)/2;



  // Let's also calculate the value between ledOn and ledOff, above which we will assume the led is on and below which we assume the led is off.

  beamThreshold = (intactValue+brokenValue)/2;



}





// Now for the loop.



void loop() {

  /* In this loop function, we're going to check to see if the beam has been broken.

  When the status of the beam changes, we'll send a Particle.publish() to the cloud

  so that if we want to, we can check from other devices when the LED is on or off.



  We'll also turn the D7 LED on when the Photoresistor detects a beam breakagse.

  */



  if (analogRead(photoresistor)>beamThreshold) {



    /* If you are above the threshold, we'll assume the beam is intact.

    If the beam was intact before, though, we don't need to change anything.

    We'll use the beamBroken flag to help us find this out.

    This flag monitors the current status of the beam.

    After the beam is broken, it is set TRUE

    and when the beam reconnects it is set to FALSE.

    */



    if (beamBroken==true) {

        // If the beam was broken before, then this is a new status.

        // We will send a publish to the cloud and turn the LED on.



        // Send a publish to your devices...

        Particle.publish("beamStatus","intact",60,PRIVATE);

        // And flash the on-board LED on and off.

        digitalWrite(boardLed,HIGH);

        delay(500);

        digitalWrite(boardLed,LOW);



        // Finally, set the flag to reflect the current status of the beam.

        beamBroken=false;

    }

    else {

        // Otherwise, this isn't a new status, and we don't have to do anything.

    }

  }



  else {

      // If you are below the threshold, the beam is probably broken.

      if (beamBroken==false) {



        // Send a publish...

        Particle.publish("beamStatus2","broken",60,PRIVATE);

        // And flash the on-board LED on and off.

        digitalWrite(boardLed,HIGH);

        delay(500);

        digitalWrite(boardLed,LOW);



        // Finally, set the flag to reflect the current status of the beam.

        beamBroken=true;

      }

      else {

          // Otherwise, this isn't a new status, and we don't have to do anything.

      }

  }



}

Сконцентрируем внимание на следующем участке кода

if (beamBroken==true) {

        // If the beam was broken before, then this is a new status.

        // We will send a publish to the cloud and turn the LED on.



        // Send a publish to your devices...

        Particle.publish("beamStatus","intact",60,PRIVATE);

        // And flash the on-board LED on and off.

        digitalWrite(boardLed,HIGH);

        delay(500);

        digitalWrite(boardLed,LOW);



        // Finally, set the flag to reflect the current status of the beam.

        beamBroken=false;

    }

Здесь видно, что если выполняется какое-то условие, то в облако отправляется событие: Particle.publish("beamStatus","intact",60,PRIVATE).

Результат получения мобильным приложением нескольких событий на скриншоте.

Screenshot_20181102-193954_Particle.jpg?

И скриншот web-консоли:

Image_18.png?timestamp=1541426819412

В заключении. 

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

Несмотря на то, что некоторые инструменты для работы с "фотоном" работают не правильно, либо не работают совсем, сам "фотон" мне понравился своими возможностями работы через облако. Да, можно и ESP прошить через OTA, но у "фотона" эта возможность существует сразу, без необходимости настраивать возможность OTA.

И наконец приведу все необходимые ссылки:

Огромная благодарность магазину DFRobot за предоставленный на обзор "фотон", ссылка на товар. 

P.S. Немного своих фотографий (я знаю, что посыпется критика из-за отсутствия фото которые сделал я лично, "даже сфоткать не мог, фоток из интернета надергал"). Фото крупные, но рука слегка дрогнула.

Коробочка пластиковая снаружи и картонная внутри. Так же же виден кружочек с логотипом Particle, не знаю зачем его вложили в коробочку с "фотоном". Внутри коробке интернет адрес, рекомендую начать с него.

IMG_0170.JPG?timestamp=1541426819413

На корпусе пара кнопок, RGB светодиод и синий светодиод, подключенный к выводу D7. На корпусе видно антенну и гнездо для подключения внешней антенны.

IMG_0175.JPG?timestamp=1541426819414

Снизу ничего нет, сейчас поймете почему.

IMG_0176.JPG?timestamp=1541426819414

Здесь видно, что выводы выведены на грань печатной платы, металлизированы и залужены. Это сделано для того, чтоб устанавливать "фотон" на печатную плату не через "пинхедеры".

IMG_0177.JPG?timestamp=1541426819414

Но "фотон" пришел с уже распаяными выводами, о чем даже указано на коробочке.

Ссылка на комментарий
Поделиться на другие сайты

  • 1 год спустя...

Симулятор контроллера, так поверхностно с большим натягом можно назвать это решение.
похоже разработчики - поколение выросшее Arduino, не до конца представляют функционал и отраслевой ISO предъявляемый  к  контроллерам.
Удаленно включить или выключить настольную лампу можно кучей способов и Particle Photon один из них.
Или они слишком поторопились, объявив новую эру, или они просто заигрались в своих грезах. 

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...