You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
22 KiB
299 lines
22 KiB
# നിങ്ങളുടെ IoT ഉപകരണം ക്ലൗഡുമായി ബന്ധിപ്പിക്കുക - Wio Terminal
|
|
|
|
ഈ പാഠഭാഗത്തിൽ, നിങ്ങളുടെ Wio Terminal നിങ്ങളുടെ IoT Hub-ലോട് കണക്റ്റ് ചെയ്ത് ടെലിമെട്രി അയയ്ക്കുകയും കമാൻഡുകൾ സ്വീകരിക്കുകയും ചെയ്യും.
|
|
|
|
## നിങ്ങളുടെ ഉപകരണം IoT Hub-ലേക്ക് കണക്റ്റ് ചെയ്യുക
|
|
|
|
അടുത്ത ഘട്ടം നിങ്ങളുടെ ഉപകരണം IoT Hub-ലേക്ക് ബന്ധിപ്പിക്കുകയാണ്.
|
|
|
|
### ടാസ്ക് - IoT Hub-ലേക്ക് കണക്റ്റ് ചെയ്യുക
|
|
|
|
1. VS Code-ൽ `soil-moisture-sensor` പ്രോജക്റ്റ് തുറക്കൂ
|
|
|
|
1. `platformio.ini` ഫയൽ തുറക്കുക. `knolleary/PubSubClient` ലൈബ്രറി ഡിപ്പെൻഡൻസി നീക്കം ചെയ്യുക. ഇത് പബ്ലിക്ക് MQTT ബ്രോക്കറുമായി കണക്റ്റ് ചെയ്യാനായി ഉപയോഗിച്ചത്, IoT Hub-ലേക്ക് കണക്റ്റ് ചെയ്യാൻ ആവശ്യമില്ല.
|
|
|
|
1. താഴെക്കൊടുത്ത ലൈബ്രറി ഡിപ്പെൻഡൻസികൾ ചേർക്കുക:
|
|
|
|
```ini
|
|
seeed-studio/Seeed Arduino RTC @ 2.0.0
|
|
arduino-libraries/AzureIoTHub @ 1.6.0
|
|
azure/AzureIoTUtility @ 1.6.1
|
|
azure/AzureIoTProtocol_MQTT @ 1.6.0
|
|
azure/AzureIoTProtocol_HTTP @ 1.6.0
|
|
azure/AzureIoTSocket_WiFi @ 1.0.2
|
|
```
|
|
|
|
`Seeed Arduino RTC` ലൈബ്രറി Wio Terminal-ൽ റിയൽ-ടൈം ക്ലോക്കുമായി ഇടപഴകാൻ കോഡ് നൽകുന്നു, സമയമനുസരിച്ച് ട്രാക്ക് ചെയ്യാൻ. ശേഷിക്കുന്ന ലൈബ്രറികൾ നിങ്ങളുടെ IoT ഉപകരണം IoT Hub-ലേക്ക് കണക്റ്റ് ചെയ്യാൻ സഹായിക്കും.
|
|
|
|
1. `platformio.ini` ഫയലിന്റെ അടിയിൽ താഴെക്കൊടുത്തത് ചേർക്കുക:
|
|
|
|
```ini
|
|
build_flags =
|
|
-DDONT_USE_UPLOADTOBLOB
|
|
```
|
|
|
|
ഇത് Arduino IoT Hub കോഡ് കമ്പൈൽ ചെയ്യുമ്പോൾ ആവശ്യമായ കോമ്പൈലർ ഫ്ലാഗ് സെറ്റ് ചെയ്യുന്നു.
|
|
|
|
1. `config.h` ഹെഡർ ഫയൽ തുറക്കുക. മുഴുവൻ MQTT സജ്ജീകരണങ്ങളും നീക്കം ചെയ്ത് ചുവടെ കൊടുത്തിരിക്കുന്ന ഡിവൈസ് കണക്ഷൻ സ്ട്രിംഗ് കോൺസ്റ്റന്റ് ചേർക്കുക:
|
|
|
|
```cpp
|
|
// ഐഒടി ഹബ് ക്രമീകരണങ്ങൾ
|
|
const char *CONNECTION_STRING = "<connection string>";
|
|
```
|
|
|
|
`<connection string>`-ന്റെ ഇടത്ത് മുൻപ് കോപ്പി ചെയ്ത നിങ്ങളുടെ ഉപകരണത്തിന്റെ കണക്ഷൻ സ്ട്രിങ്ങ് വച്ചിടുക.
|
|
|
|
1. IoT Hub-ലേക്ക് കണക്ഷൻ സമയം അടിസ്ഥാനമായ ടോക്കൺ ഉപയോഗിക്കുന്നു. അതായത്, IoT ഉപകരണം നിലവിലെ സമയം അറിയണം. Windows, macOS, Linux പോലുള്ള ഓപ്പറേറ്റിംഗ് സിസ്റ്റങ്ങളുപോലെ, മൈക്രോകൺട്രോളറുകൾ ഇന്റർനെറ്റിലൂടെ സ്വയം സമയം സിങ്ക് ചെയ്യുന്നതല്ല. അതിനാൽ [NTP](https://wikipedia.org/wiki/Network_Time_Protocol) സർവറിൽ നിന്നുള്ള നിലവിലെ സമയം നേടാൻ കോഡ് ചേർക്കേണ്ടതാണ്. സമയം കിട്ടിയ ശേഷം, അത് Wio Terminal-ലെ റിയൽ-ടൈം ക്ലോക്കിൽ സംഭരിക്കാം, ഉപകരണം പവർ നഷ്ടമാക്കാതെ കൃത്യമായ സമയമറിയാം. `ntp.h` എന്ന പുതിയ ഫയൽ താഴെക്കൊടുത്ത കോഡോടുകൂടി ചേർക്കുക:
|
|
|
|
```cpp
|
|
#pragma once
|
|
|
|
#include "DateTime.h"
|
|
#include <time.h>
|
|
#include "samd/NTPClientAz.h"
|
|
#include <sys/time.h>
|
|
|
|
static void initTime()
|
|
{
|
|
WiFiUDP _udp;
|
|
time_t epochTime = (time_t)-1;
|
|
NTPClientAz ntpClient;
|
|
|
|
ntpClient.begin();
|
|
|
|
while (true)
|
|
{
|
|
epochTime = ntpClient.getEpochTime("0.pool.ntp.org");
|
|
|
|
if (epochTime == (time_t)-1)
|
|
{
|
|
Serial.println("Fetching NTP epoch time failed! Waiting 2 seconds to retry.");
|
|
delay(2000);
|
|
}
|
|
else
|
|
{
|
|
Serial.print("Fetched NTP epoch time is: ");
|
|
|
|
char buff[32];
|
|
sprintf(buff, "%.f", difftime(epochTime, (time_t)0));
|
|
Serial.println(buff);
|
|
break;
|
|
}
|
|
}
|
|
|
|
ntpClient.end();
|
|
|
|
struct timeval tv;
|
|
tv.tv_sec = epochTime;
|
|
tv.tv_usec = 0;
|
|
|
|
settimeofday(&tv, NULL);
|
|
}
|
|
```
|
|
|
|
ഈ കോഡിന്റെ വിശദാംശങ്ങൾ ഈ പാഠഭാഗത്തിന്റെ പരിധിയ്ക്ക് പുറത്താണ്. `initTime` എന്ന ഫംഗ്ഷൻ നിർവ്വചിക്കുന്നു, NTP സർവറിൽ നിന്നുള്ള സമയം വാങ്ങി Wio Terminal-ലെ ക്ലോക്ക് സെറ്റ് ചെയ്യാൻ ഉപയോഗിക്കുന്നു.
|
|
|
|
1. `main.cpp` ഫയൽ തുറന്ന് മുഴുവൻ MQTT കോഡ് നീക്കം ചെയ്യുക, `PubSubClient.h` ഹെഡർ ഫയൽ, `PubSubClient` വേരിയേബിൾ പ്രഖ്യാപനവും, `reconnectMQTTClient` மற்றும் `createMQTTClient` രീതികൾ, ശുപാർശകളും നീക്കം ചെയ്യുക. ഈ ഫയൽ WiFi കണക്റ്റ് ചെയ്യുന്നതിനുള്ള, മണ്ണ് തോര്യത കൈമാറുന്നതിനുള്ള, JSON ഡോക്യുമെന്റ് സൃഷ്ടിക്കുന്നതിനുള്ള കോഡ് മാത്രമേ ഉള്ളൂ.
|
|
|
|
1. `main.cpp` ഫയലിന്റെ മുകളിൽ താഴെക്കൊടുത്ത `#include` നിർദ്ദേശങ്ങൾ ചേർക്കുക, IoT Hub ലൈബ്രറികൾക്കും സമയ സെറ്റിംഗിനും:
|
|
|
|
```cpp
|
|
#include <AzureIoTHub.h>
|
|
#include <AzureIoTProtocol_MQTT.h>
|
|
#include <iothubtransportmqtt.h>
|
|
#include "ntp.h"
|
|
```
|
|
|
|
1. `setup` ഫംഗ്ഷന്റെ അവസാനം നിലവിലെ സമയം സെറ്റ് ചെയ്യാൻ താഴെക്കൊടുത്ത കോൾ ചേർക്കുക:
|
|
|
|
```cpp
|
|
initTime();
|
|
```
|
|
|
|
1. ഫയലിന്റെ മുകളിൽ, `#include` നിർദ്ദേശങ്ങളുടെ താഴെ, താഴെക്കൊടുത്ത വേരിയേബിൾ പ്രഖ്യാപനം ചേർക്കുക:
|
|
|
|
```cpp
|
|
IOTHUB_DEVICE_CLIENT_LL_HANDLE _device_ll_handle;
|
|
```
|
|
|
|
ഇത് ഒരു `IOTHUB_DEVICE_CLIENT_LL_HANDLE` പ്രഖ്യാപിക്കുന്നു, IoT Hub-ലേക്ക് കണക്ഷൻ കൈകാര്യം ചെയ്യാനുള്ള ഹാൻഡിൽ.
|
|
|
|
1. ഇതിന് താഴെ, താഴെക്കൊടുത്ത കോഡ് ചേർക്കുക:
|
|
|
|
```cpp
|
|
static void connectionStatusCallback(IOTHUB_CLIENT_CONNECTION_STATUS result, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void *user_context)
|
|
{
|
|
if (result == IOTHUB_CLIENT_CONNECTION_AUTHENTICATED)
|
|
{
|
|
Serial.println("The device client is connected to iothub");
|
|
}
|
|
else
|
|
{
|
|
Serial.println("The device client has been disconnected");
|
|
}
|
|
}
|
|
```
|
|
|
|
ഇത് ഒരു കോൾബാക്ക് ഫംഗ്ഷൻ പ്രഖ്യാപിക്കുന്നു, IoT Hub-ലേക്ക് കണക്ഷൻ നില മാറുമ്പോൾ (കണക്റ്റ് ചെയ്യുക അല്ലെങ്കിൽ ഡിസ്കണക്റ്റ് ചെയ്യുക) വിളിക്കപ്പെടും. നില സീരിയൽ പോർട്ടിലേക്ക് അയയ്ക്കുന്നു.
|
|
|
|
1. ഇതിന് താഴെ, IoT Hub-ലേക്ക് കണക്റ്റ് ചെയ്യാനുള്ള ഫംഗ്ഷൻ ചേർക്കുക:
|
|
|
|
```cpp
|
|
void connectIoTHub()
|
|
{
|
|
IoTHub_Init();
|
|
|
|
_device_ll_handle = IoTHubDeviceClient_LL_CreateFromConnectionString(CONNECTION_STRING, MQTT_Protocol);
|
|
|
|
if (_device_ll_handle == NULL)
|
|
{
|
|
Serial.println("Failure creating Iothub device. Hint: Check your connection string.");
|
|
return;
|
|
}
|
|
|
|
IoTHubDeviceClient_LL_SetConnectionStatusCallback(_device_ll_handle, connectionStatusCallback, NULL);
|
|
}
|
|
```
|
|
|
|
ഈ കോഡ് IoT Hub ലൈബ്രറി ഇൻഷ്യലൈസ് ചെയ്യുന്നു, ശേഷം `config.h` ഫയലിലുള്ള കണക്ഷൻ സ്ട്രിങ്ങ് ഉപയോഗിച്ച് MQTT അടിസ്ഥാനത്തിലുള്ള കണക്ഷൻ സൃഷ്ടിക്കുന്നു. കണക്ഷൻ പരാജയപ്പെടുന്നുവെങ്കിൽ, സീരിയൽ പോർട്ടിലേക്ക് പിഴവ് അയയ്ക്കുന്നു - ഇതു വന്നാൽ കണക്ഷൻ സ്ട്രിങ്ങ് പരിശോധിക്കുക. അവസാനം കണക്ഷൻ നില കോൾബാക്ക് സെറ്റ് ചെയ്യുന്നു.
|
|
|
|
1. ഈ ഫംഗ്ഷൻ `setup` ഫംഗ്ഷനിൽ `initTime` കോൾക്ക് താഴെ വിളിക്കുക:
|
|
|
|
```cpp
|
|
connectIoTHub();
|
|
```
|
|
|
|
1. MQTT ക്ലയന്റ് പോലെയാണീ കോഡും single thread- ൽ പ്രവർത്തിക്കുന്നത് എന്നതിനാൽ ഹബ് വഴി അയക്കുന്ന സന്ദേശങ്ങൾ പ്രോസസ് ചെയ്യാൻ സമയമെടുക്കും. അതിനാൽ `loop` ഫംഗ്ഷന്റെ മുകളിൽ താഴെക്കൊടുത്തത് ചേർക്കുക:
|
|
|
|
```cpp
|
|
IoTHubDeviceClient_LL_DoWork(_device_ll_handle);
|
|
```
|
|
|
|
1. ഈ കോഡ് കമ്പൈൽ ചെയ്ത് അപ്ലോഡ് ചെയ്യുക. സീരിയൽ മോണിറ്ററിൽ കണക്ഷൻ കാണാം:
|
|
|
|
```output
|
|
Connecting to WiFi..
|
|
Connected!
|
|
Fetched NTP epoch time is: 1619983687
|
|
Sending telemetry {"soil_moisture":391}
|
|
The device client is connected to iothub
|
|
```
|
|
|
|
ഔട്ട്പുട്ടിൽ NTP സമയം ലഭിക്കുന്നത്, തുടർന്ന് ഉപകരണം കണക്റ്റ് ആകുന്നത് കാണാം. കണക്ഷൻ പതുക്കെ ആയതിനാൽ, കണക്റ്റ് ചെയ്യുമ്പോൾ മണ്ണ് തോര്യത ഔട്ട്പുട്ടിൽ കാണാമാകാം.
|
|
|
|
> 💁 UNIX സമയത്തെ വായനാസഹജമായ രൂപത്തിലേക്ക് മാറ്റാൻ [unixtimestamp.com](https://www.unixtimestamp.com) പോലുള്ള വെബ്സൈറ്റ് ഉപയോഗിക്കാം.
|
|
|
|
## ടെലിമെട്രി അയയ്ക്കുക
|
|
|
|
ഇപ്പോൾ നിങ്ങളുടെ ഉപകരണം കണക്റ്റ് ചെയ്തതിനാൽ, MQTT ബ്രോക്കറിന് പകരം IoT Hub-ലേക്ക് ടെലിമെട്രി അയയ്ക്കാൻ കഴിയും.
|
|
|
|
### ടാസ്ക് - ടെലിമെട്രി അയയ്ക്കുക
|
|
|
|
1. `setup` ഫംഗ്ഷനു മുകളിൽ താഴെക്കൊടുത്ത ഫംഗ്ഷൻ ചേർക്കുക:
|
|
|
|
```cpp
|
|
void sendTelemetry(const char *telemetry)
|
|
{
|
|
IOTHUB_MESSAGE_HANDLE message_handle = IoTHubMessage_CreateFromString(telemetry);
|
|
IoTHubDeviceClient_LL_SendEventAsync(_device_ll_handle, message_handle, NULL, NULL);
|
|
IoTHubMessage_Destroy(message_handle);
|
|
}
|
|
```
|
|
|
|
ഈ കോഡ് സ്ട്രിങ്ങ് പാരാമീറ്ററായി ലഭിച്ച മാസേജിൽ നിന്ന് IoT Hub സന്ദേശം സൃഷ്ടിക്കുന്നു, ഹബ്-ലേക്ക് അയയ്ക്കുന്നു, തുടർന്ന് മെസേജ് ഒബ്ജക്ട് ക്ലീൻ ചെയ്യുന്നു.
|
|
|
|
1. `loop` ഫംഗ്ഷനിൽ ടെലിമെട്രി സീരിയൽ പോർട്ടിൽ അയയ്ക്കുന്ന വരിയ്ക്ക് അടുത്ത് താഴെക്കൊടുത്ത കോൾ ചേർക്കുക:
|
|
|
|
```cpp
|
|
sendTelemetry(telemetry.c_str());
|
|
```
|
|
|
|
## കമാൻഡുകൾ കൈകാര്യം ചെയ്യുക
|
|
|
|
സെർവർ കോഡിൽ നിന്നുള്ള റീലേ കൺട്രോൾ ചെയ്യാനുള്ള കമാൻഡുകൾ കൈകാര്യം ചെയ്യേണ്ടതുണ്ട്. ഇത് ഡയരക്റ്റ് മെത്തഡ് റിക്വസ്റ്റ് എന്ന രൂപത്തിൽ അയയ്ക്കുന്നു.
|
|
|
|
## ടാസ്ക് - ഡയരക്റ്റ് മെത്തഡ് റിക്വസ്റ്റ് ഹാൻഡിൽ ചെയ്യുക
|
|
|
|
1. `connectIoTHub` ഫംഗ്ഷനിലേക്ക് മുമ്പ് താഴെക്കൊടുത്ത കോഡ് ചേർക്കുക:
|
|
|
|
```cpp
|
|
int directMethodCallback(const char *method_name, const unsigned char *payload, size_t size, unsigned char **response, size_t *response_size, void *userContextCallback)
|
|
{
|
|
Serial.printf("Direct method received %s\r\n", method_name);
|
|
|
|
if (strcmp(method_name, "relay_on") == 0)
|
|
{
|
|
digitalWrite(PIN_WIRE_SCL, HIGH);
|
|
}
|
|
else if (strcmp(method_name, "relay_off") == 0)
|
|
{
|
|
digitalWrite(PIN_WIRE_SCL, LOW);
|
|
}
|
|
}
|
|
```
|
|
|
|
IoT Hub ലൈബ്രറി ഡയരക്റ്റ് മെത്തഡ് റിക്വസ്റ്റ് ലഭിക്കുമ്ബോള് വിളിച്ചേക്കാവുന്ന കോൾബാക്ക് രീതിയാണ് ഇത്. അഭ്യർത്ഥിച്ച മെത്തഡ് `method_name` പാരാമീറ്ററിൽ ഉണ്ടാകും. ഈ ഫംഗ്ഷൻ വിളിച്ച മെത്തഡ് സീരിയൽ പോർട്ടിൽ പ്രിന്റ് ചെയ്യും, തുടർന്ന് മെത്തഡ് അനുസരിച്ച് റീലേ ഓണോ ഓഫ് ആക്കും.
|
|
|
|
> 💁 ഇത് ഒരേ ഡയരക്റ്റ് മെത്തഡ് റിക്വസ്റ്റ് വഴി നടപ്പിലാക്കാം, റീലേയുടെ ആഗ്രഹിക്കുന്ന നില മെത്തഡ് അഭ്യർത്ഥനയോടൊപ്പം പാരാമീറ്ററായി പാസ്സ് ചെയ്യുക, ഇത് `payload`-ൽ നിന്നും ലഭിക്കും.
|
|
|
|
1. `directMethodCallback` ഫംഗ്ഷന്റെ അവസാനം താഴെക്കൊടുത്ത കോഡ് ചേർക്കുക:
|
|
|
|
```cpp
|
|
char resultBuff[16];
|
|
sprintf(resultBuff, "{\"Result\":\"\"}");
|
|
*response_size = strlen(resultBuff);
|
|
*response = (unsigned char *)malloc(*response_size);
|
|
memcpy(*response, resultBuff, *response_size);
|
|
|
|
return IOTHUB_CLIENT_OK;
|
|
```
|
|
|
|
ഡയരക്റ്റ് മെത്തഡ് അഭ്യർത്ഥനകൾക്ക് റസ്പോൺസ് ആവശ്യമാണ്, അത് രണ്ട് ഭാഗങ്ങൾ - ടെക്സ്റ്റ് റസ്പോൺസ്, റിട്ടേൺ കോഡ്. ഈ കോഡ് ചുവടെ കൊടുത്ത JSON ഫോർമാറ്റിൽ ഫലം ഉണ്ടാക്കും:
|
|
|
|
```JSON
|
|
{
|
|
"Result": ""
|
|
}
|
|
```
|
|
|
|
ഇത് `response` പാരാമീറ്ററിലേക്ക് കോപ്പി ചെയ്യും, `response_size`-ൽ വലിപ്പം നൽകും. പിന്നീട് `IOTHUB_CLIENT_OK` റിട്ടേൺ ചെയ്യുന്നു, മെത്തഡ് ശരിയായി കൈകാര്യം ചെയ്തതായി സൂചിപ്പിക്കാൻ.
|
|
|
|
1. കോൾബാക്ക് ബന്ധിപ്പിക്കാൻ `connectIoTHub` ഫംഗ്ഷന്റെ അവസാനം താഴെ കൊടുത്തത് ചേർക്കുക:
|
|
|
|
```cpp
|
|
IoTHubClient_LL_SetDeviceMethodCallback(_device_ll_handle, directMethodCallback, NULL);
|
|
```
|
|
|
|
1. `loop` ഫംഗ്ഷൻ IoTHubDeviceClient_LL_DoWork ഫംഗ്ഷൻ കോൾചെയ്തു ഹബ് അയക്കുന്ന ഇവന്റുകൾ പ്രോസസ് ചെയ്യും. ഇത് ഓരോ 10 സെക്കൻഡുകൾക്ക് ഒരിക്കൽ `delay` മൂലം മാത്രമാണ് വിളിക്കപ്പെടുക, അതിനാൽ ഡയരക്റ്റ് മെത്തഡ് പ്രോസസിങ് 10 സെക്കൻഡ് ഇടവേള മാത്രമേ ഉണ്ടായിരിക്കൂ. ഇത് കാര്യക്ഷമമാക്കാൻ 10 സെക്കൻഡ് ഡിലേ പല ചെറിയ ഡിലേഷനായി മാറ്റി ഓരോ പ്രാവശ്യം `IoTHubDeviceClient_LL_DoWork` വിളിക്കാം. അതിനായി `loop`-ക്ക് മുൻപ് താഴെക്കൊടുത്ത കോഡ് ചേർക്കുക:
|
|
|
|
```cpp
|
|
void work_delay(int delay_time)
|
|
{
|
|
int current = 0;
|
|
do
|
|
{
|
|
IoTHubDeviceClient_LL_DoWork(_device_ll_handle);
|
|
delay(100);
|
|
current += 100;
|
|
} while (current < delay_time);
|
|
}
|
|
```
|
|
|
|
ഈ കോഡ് ആവർത്തിച്ച് പ്രവർത്തിക്കുകയാണ്, ഓരോ തവണയും `IoTHubDeviceClient_LL_DoWork` വിളിച്ച് 100ms ഡിലേ ചെയ്യുന്നു. ഇത് `delay_time` പാരാമീറ്ററിൽ നൽകിയ സമയത്തേക്ക് ആവശ്യത്തിന് ആവരും. അതായത്, ഉപകരണം കൂടുതൽ 100ms ഉണ്ടാകാതെ ഡയരക്റ്റ് മെത്തഡ് അഭ്യർത്ഥനകൾ പ്രാസസ്സ് ചെയ്യാൻ സാധിക്കും.
|
|
|
|
1. `loop` ഫംഗ്ഷനിൽ `IoTHubDeviceClient_LL_DoWork` കോൾ നീക്കം ചെയ്ത് `delay(10000)` താഴെക്കൊടുത്ത കോഡിൽ മാറ്റുക:
|
|
|
|
```cpp
|
|
work_delay(10000);
|
|
```
|
|
|
|
> 💁 ഈ കോഡ് [code/wio-terminal](../../../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud/code/wio-terminal) ഫോളഡറിൽ ലഭ്യമാണ്.
|
|
|
|
😀 നിങ്ങളുടെ മണ്ണ് തോര്യത സെൻസർ പ്രോഗ്രാം നിങ്ങളുടെ IoT Hub-ലിനോട് കണക്റ്റ് ചെയ്തു!
|
|
|
|
---
|
|
|
|
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
|
|
**അസൂയപ്പെടുത്തൽ**:
|
|
ഈ രേഖ AI വിവർത്തന സേവനം [Co-op Translator](https://github.com/Azure/co-op-translator) ഉപയോഗിച്ച് വിവർത്തനം ചെയ്തതാണ്. നാം സതിനിശ്ചിതത്വം ഉറപ്പാക്കാനുള്ള ശ്രമം നടത്തുന്നെങ്കിലും, ഓട്ടോമാറ്റിക് വിവർത്തനങ്ങളിൽ പിശകുകളോ അക്ഷമതകളോ ഉണ്ടാകാം എന്നതിന് ദയവായി ശ്രദ്ധിക്കുക. മാതൃഭാഷയിലെ യഥാർത്ഥ രേഖ authoritative ഉറവിടമായിരിക്കണം. നിർണ്ണായക വിവരങ്ങൾക്ക്, പ്രൊഫഷണൽ മനുഷ്യ വിവർത്തനം ശുപാർശ ചെയ്തതാണ്. ഈ വിവർത്തനം ഉപയോഗിച്ചുനിലവിലെ തെറ്റുകൾ അല്ലെങ്കിൽ തെറ്റിദ്ധാരണകൾക്ക 우리는 ഉത്തരവാദികൾ അല്ല.
|
|
<!-- CO-OP TRANSLATOR DISCLAIMER END --> |