Giter VIP home page Giter VIP logo

hydrate-extension-inteligente's People

Contributors

frozen-burrito avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

hydrate-extension-inteligente's Issues

[BUG] El driver de BLE no crea los servicios GATT

Descripción del Error
El driver BLE es inicializado con éxito y puede entrar en estado de ADVERTISING, pero al ser emparejado con un dispositivo periférico, se puede observar que el driver BLE solo creó los servicios por default de un servidor GATT (Generic Attribute y Generic Access). Los servicios Hydrate y Batería no son inicializados ni usados en el perfil GATT.

Cómo Reproducir
Pasos para reproducir el error:

  1. Programar el chip ESP32 con la versión 1.0.0+2 actual.
  2. Monitorear el chip a través de consola.
  3. Emparejar la extensión de botellas con un dispositivo periférico.
  4. Usar software con capacidad de analizar servidores GATT desde el dispositivo periférico para observar que los servicios esperados no son accesibles.

Comportamiento Esperado
Cuando la extensión para botellas es emparejada con un dispositivo periférico (un dispositivo móvil, en este caso) debería hacer accesibles los servicios GATT Hydrate y Batería, con sus UUID correspondientes, para que la app de Hydrate pueda obtener los registros de hidratación.

Screenshots
Los servicios descubiertos en el dispositivo embebido desde la app nRF Connect:

Screenshot_20220915-065955_nRF Connect

Entorno

  • Módulo ESP-32: ESP-32
  • Versión de ESP-IDF: v4.4
  • Versión de software de aplicación: 1.0.0+2

Contexto Adicional
Los logs producidos por el dispositivo a través de idf.py -p <PORT> monitor al inicializar el dispositivo pueden ser observados a continuación:

I (29) boot: ESP-IDF v4.4.1 2nd stage bootloader
I (29) boot: compile time 14:02:38
I (29) boot: chip revision: 3
I (32) boot_comm: chip revision: 3, min. bootloader chip revision: 0
I (39) boot.esp32: SPI Speed      : 40MHz
I (44) boot.esp32: SPI Mode       : DIO
I (48) boot.esp32: SPI Flash Size : 2MB
I (53) boot: Enabling RNG early entropy source...
I (58) boot: Partition Table:
I (62) boot: ## Label            Usage          Type ST Offset   Length
I (69) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (76) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (84) boot:  2 factory          factory app      00 00 00010000 00100000
I (91) boot: End of partition table
I (96) boot_comm: chip revision: 3, min. application chip revision: 0
I (103) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=1d9e8h (121320) map
I (155) esp_image: segment 1: paddr=0002da10 vaddr=3ffbdb60 size=02608h (  9736) load
I (159) esp_image: segment 2: paddr=00030020 vaddr=400d0020 size=7aaech (502508) map
I (343) esp_image: segment 3: paddr=000aab14 vaddr=3ffc0168 size=020e0h (  8416) load
I (346) esp_image: segment 4: paddr=000acbfc vaddr=40080000 size=171d4h ( 94676) load
I (387) esp_image: segment 5: paddr=000c3dd8 vaddr=50000000 size=00010h (    16) load
I (399) boot: Loaded app from partition at offset 0x10000
I (399) boot: Disabling RNG early entropy source...
I (411) cpu_start: Pro cpu up.
I (411) cpu_start: Starting app cpu, entry point is 0x400811e4
0x400811e4: call_start_cpu1 at C:/Espressif/frameworks/esp-idf-v4.4.1-2/components/esp_system/port/cpu_start.c:160

I (0) cpu_start: App cpu up.
I (427) cpu_start: Pro cpu start user code
I (427) cpu_start: cpu freq: 160000000
I (427) cpu_start: Application information:
I (432) cpu_start: Project name:     nvs-test
I (437) cpu_start: App version:      1
I (441) cpu_start: Compile time:     Sep  9 2022 14:01:36
I (447) cpu_start: ELF file SHA256:  a189ec326b5c14a4...
I (453) cpu_start: ESP-IDF:          v4.4.1
I (459) heap_init: Initializing. RAM available for dynamic allocation:
I (466) heap_init: At 3FFAFF10 len 000000F0 (0 KiB): DRAM
I (472) heap_init: At 3FFB6388 len 00001C78 (7 KiB): DRAM
I (478) heap_init: At 3FFB9A20 len 00004108 (16 KiB): DRAM
I (484) heap_init: At 3FFC6B38 len 000194C8 (101 KiB): DRAM
I (490) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (496) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (503) heap_init: At 400971D4 len 00008E2C (35 KiB): IRAM
I (510) spi_flash: detected chip: generic
I (514) spi_flash: flash io: dio
W (518) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (532) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (582) MAIN: Size minimo de heap libre: 227012 bytes
I (3582) BTDM_INIT: BT controller compile version [5688ed5]
I (3582) system_api: Base MAC address is not set
I (3582) system_api: read default base MAC address from EFUSE
I (3582) MAIN: NVS inicializado
I (3592) phy_init: phy_version 4670,719f9f6,Feb 18 2021,17:07:07
I (3582) BLE: Estado de BLE: Initializing
I (3702) MAIN: Nuevo registro de hidratacion generado: { water: 74, temp: -2, bat: 16, time: 3}
I (3702) MAIN: Nuevo registro de hidratacion enviado para almacenamiento, total 1
I (3702) BLE: Estado de BLE: Initializing
I (4032) BLE: Tabla de atributos creada, handle = 23
I (4032) BLE: Servicios inicializados con exito
E (4032) BT_APPL: service not created

I (4032) BLE: SERVICE_START_EVT, status 0, service_handle = 40
I (4052) BLE: Advertising comenzado
I (4212) BLE: Estado de BLE: Advertising
(...)

Notar el mensaje de error E (4032) BT_APPL: service not created, parece un indicador del problema.

[DOCS] Falta agregar un README.md al proyecto

El archivo README.md debería describir:

  1. Las instrucciones para instalar y probar localmente el proyecto
  2. Los componentes (driver de BLE, nvs, sensores) que forman parte del proyecto y están incluidos en el directorio components.
  3. Links útiles para recursos informativos.

[BUG] Intentar obtener los registros desde NVS para sincronizarlos resulta en `ESP_ERR_NVS_NOT_FOUND`

Descripción del Error
Cuando la extensión de la botella entra en modo de sincronización e intenta obtener los registros de hidratación almacenados en NVS, puede obtener un solo registro y luego produce un error ESP_ERR_NVS_NOT_FOUND para los cuatro registros restantes (la extensión puede almacenar hasta 5 registros de hidratación en NVS).

Cómo Reproducir
Pasos para reproducir el error:

  1. Inicializar la extensión de botella, con la versión 1.0.0+2 actual programada en el ESP32.
  2. Esperar un momento a que varios registros de hidratación sean producidos y almacenados en NVS.
  3. Hacer que la extensión entre en modo de sincronización (emparejándola con un dispositivo periférico por BLE).
  4. Observar los errores de NVS resultantes.

Comportamiento Esperado
Al entrar en modo de sincronización, la extensión para botellas debería sincronizar todos los registros encontrados en xSyncQueue, los registros previamente enviados a xStorageQueue, y los registros almacenados en NVS (hasta 5 de los últimos).

Entorno

  • Módulo ESP-32: ESP-32
  • Versión de ESP-IDF: v4.4
  • Versión de software de aplicación: 1.0.0+2

Contexto Adicional
Es muy probable que el problema esté relacionado con los índices de acceso a entradas de NVS (el parámetro index, recibido por la función get_hydration_record() en storage.h. También es posible que el problema esté en la forma que se obtienen las keys para NVS (obtenerlas según el índice, como water_amount_1 y water_amount_2 corresponden a los registros con índice 1 y 2, respectivamente).

Los logs producidos antes, durante y después de uno de los varios eventos de error producidos por la extensión de botellas:

(...)
I (33762) MAIN: Nuevo registro de hidratacion generado: { water: 410, temp: 13, bat: 0, time: 33}
I (33762) MAIN: Nuevo registro de hidratacion enviado para almacenamiento, total 7
I (33832) BLE: Estado de BLE: Advertising
I (34352) BLE: Estado de BLE: Advertising
I (34852) BLE: Estado de BLE: Advertising
I (35262) BLE: Estado de BLE: Advertising
I (35262) MAIN: Estado de conexion BLE: sin emparejar
I (35352) BLE: Estado de BLE: Advertising
I (35852) BLE: Estado de BLE: Advertising
I (36352) BLE: Estado de BLE: Advertising
I (36852) BLE: Estado de BLE: Advertising
I (37352) BLE: Estado de BLE: Advertising
I (37852) BLE: Estado de BLE: Advertising
I (38352) BLE: Estado de BLE: Advertising
I (38772) BLE: Estado de BLE: Advertising
I (38772) MAIN: Nuevo registro de hidratacion generado: { water: 981, temp: 18, bat: 38, time: 38}
I (38772) MAIN: Nuevo registro de hidratacion enviado para almacenamiento, total 8
I (38852) BLE: Estado de BLE: Advertising
I (39372) BLE: Estado de BLE: Advertising
I (39872) BLE: Estado de BLE: Advertising
I (40372) BLE: Estado de BLE: Advertising
I (40512) BLE: Estado de BLE: Advertising
I (40512) MAIN: Estado de conexion BLE: sin emparejar
I (40872) BLE: Estado de BLE: Advertising
I (41372) BLE: Estado de BLE: Advertising
I (41872) BLE: Estado de BLE: Advertising
I (42372) BLE: Estado de BLE: Advertising
I (42872) BLE: Estado de BLE: Advertising
I (43372) BLE: Estado de BLE: Advertising
I (43782) BLE: Estado de BLE: Advertising
I (43782) MAIN: Nuevo registro de hidratacion generado: { water: 929, temp: 16, bat: 15, time: 43}
I (43782) MAIN: Nuevo registro de hidratacion enviado para almacenamiento, total 9
I (43872) BLE: Estado de BLE: Advertising
I (44392) BLE: Estado de BLE: Advertising
I (44432) BLE: ESP_GATTS_CONNECT_EVT, conn_id = 0
I (44432) BLE: 56 21 25 a3 99 43
I (44432) BLE: Estado de BLE: Paired
I (44692) BLE: Estado de BLE: Paired
I (44832) BLE: Parámetros de conexión actualizados:
status = 0
min_int = 16
max_int = 32
conn_int = 24
latency = 0
timeout = 400
I (44892) BLE: Estado de BLE: Paired
I (44892) MAIN: Numero de registros almacenados: 5
I (44902) MAIN: Registro obtenido de NVS: (indice 0) { water: 929, temp: 16, bat: 15, time: 43}
W (44902) STORAGE: Error de lectura de NVS (1/4): ESP_ERR_NVS_NOT_FOUND
E (44912) MAIN: Error al recuperar registro desde NVS (ESP_ERR_NVS_NOT_FOUND)
W (44922) STORAGE: Error de lectura de NVS (1/4): ESP_ERR_NVS_NOT_FOUND
E (44922) MAIN: Error al recuperar registro desde NVS (ESP_ERR_NVS_NOT_FOUND)
W (44932) STORAGE: Error de lectura de NVS (1/4): ESP_ERR_NVS_NOT_FOUND
E (44942) MAIN: Error al recuperar registro desde NVS (ESP_ERR_NVS_NOT_FOUND)
I (44942) BLE: Estado de BLE: Paired
I (44952) BLE: Registro convertido a buffers para ser sincronizado: { water: [0XA1,0X3], temp: [0X10,0], bat: 15, time: [0X2B,0,0,0]}
W (44962) STORAGE: Error de lectura de NVS (1/4): ESP_ERR_NVS_NOT_FOUND
E (44972) MAIN: Error al recuperar registro desde NVS (ESP_ERR_NVS_NOT_FOUND)
I (45122) BLE: Parámetros de conexión actualizados:
status = 0
min_int = 0
max_int = 0
conn_int = 6
latency = 0
timeout = 500
W (45212) MAIN: Registro sincronizado, pero no obtenido por cliente, restantes = 1
I (45212) BLE: Registro convertido a buffers para ser sincronizado: { water: [0XA1,0X3], temp: [0X10,0], bat: 15, time: [0X2B,0,0,0]}
I (45262) BLE: Parámetros de conexión actualizados:
status = 0
min_int = 0
max_int = 0
conn_int = 24
latency = 0
timeout = 400
W (45472) MAIN: Registro sincronizado, pero no obtenido por cliente, restantes = 1
I (45472) BLE: Registro convertido a buffers para ser sincronizado: { water: [0XA1,0X3], temp: [0X10,0], bat: 15, time: [0X2B,0,0,0]}
I (45482) BLE: Estado de BLE: Paired
(...)

[BUG] Los registros en queue de sincronizar se mantienen ahí cuando la app se desconecta del dispositivo

Descripción del Error
Los registros de hidratación generados por el dispositivos pueden ser enviados a una de dos queues: xStorageQueue y xSyncQueue. Cuando la app está conectada con BLE, los registros son enviados a xSyncQueue. Sin embargo, cuando la app se desconecta del dispositivo, los registros se mantienen en xSyncQueue. Si el dispositivo entra en deep sleep o se reinicia, los registros de hidratación son perdidos.

Cómo Reproducir
Pasos para reproducir el error:

  1. Registrar varios consumos de hidratación con el dispositivo.
  2. Conectar la app con el dispositivo.
  3. Antes de que todos los registros hayan sido sincronizados, desconectar la app del dispositivo.
  4. Reiniciar (o esperar a que entre en deep sleep) el dispositivo.
  5. Volver a iniciar el dispositivo, notar que los registros que quedaron en xSyncQueue no fueron almacenados en NVS

Comportamiento Esperado
La task de comunicación debería regresar los registros encontrados en xSyncQueue a la task de almacenamiento, removiéndolos de xSyncQueue y agregándolos a xStorageQueue.

Entorno

  • Módulo ESP-32: ESP-32-WROOM-32E
  • Versión de ESP-IDF: v4.4
  • Versión de software de aplicación: 1.0.0+1

[FEATURE] Definir una partición de NVS dedicada para almacenar los registros de hidratación

La funcionalidad que sugieres surgió de un problema? Por favor descríbelo.
No existe un problema con el almacenamiento en NVS por ahora, pero si en un futuro se decide almacenar más información distinta en NVS o incrementar la cantidad de registros que pueden ser almacenados, sería probable que la información quedara desordenada, difícil de gestionar e incluso poco optimizada para lectura y escritura.

Describe la solución que te gustaría
La sugerencia es definir una partición de NVS dedicada a almacenar los registros de hidratación, separando estos datos de la demás información almacenada en NVS (como la que es usada por bluetooth). Facilitaría la gestión del almacenamiento.

Describe las alternativas que has considerado
Por el momento, usar NVS particiones dedicadas (a parte de las creadas por default por ESP-IDF) funciona bien. Pero no es la mejor forma de gestionar la memoria no volátil.

[BUG] Las mediciones del MPU6050 son afectadas cuando se activa el uso de sueño profundo

Descripción del Error
Cuando se activa el uso de sueño profundo para economizar energía, todas las mediciones obtenidas del MPU6050 (giroscopio, aceleración y temperatura) son 0.

Cómo Reproducir
Pasos para reproducir el error:

  1. Activar USE_DEEP_SLEEP y LIGHT_SLEEP_ENABLED en la configuración personalizada de menuconfig. Asegurar que el uso del procesador ULP está activado.
  2. Programar el chip ESP32 con el software de aplicación 1.0.0+1
  3. Notar las mediciones erróneas del sensor.

Comportamiento Esperado
La operación normal del módulo no debería ser impedida completamente al usar ahorro de energía por sueño profundo. El sistema debería modificar su comportamiento según el esquema de energía, sin que afecte la detección de hidratación, conectividad o almacenamiento.

Entorno

  • Módulo ESP-32: ESP-32, rev. 3
  • Versión de ESP-IDF: v4.4.1
  • Versión de software de aplicación: 1.0.0+1

Contexto Adicional
El estado del sensor producido después de su inicialización es ESP_ERR_TIMEOUT.

Los logs completos de inicialización del sistema (todas las mediciones siguientes tienen los mismos valores para el MPU6050):

I (0) cpu_start: App cpu up.
I (452) cpu_start: Pro cpu start user code
I (452) cpu_start: cpu freq: 160000000
I (452) cpu_start: Application information:
I (457) cpu_start: Project name:     extension-inteligente-hydrate
I (464) cpu_start: App version:      1614ba6-dirty
I (469) cpu_start: Compile time:     Oct 13 2022 11:17:14
I (475) cpu_start: ELF file SHA256:  f611e463cbfd01f6...
I (481) cpu_start: ESP-IDF:          v4.4.1
I (486) heap_init: Initializing. RAM available for dynamic allocation:
I (493) heap_init: At 3FFAFF10 len 000000F0 (0 KiB): DRAM
I (499) heap_init: At 3FFB6388 len 00001C78 (7 KiB): DRAM
I (505) heap_init: At 3FFB9A20 len 00004108 (16 KiB): DRAM
I (512) heap_init: At 3FFC7218 len 00018DE8 (99 KiB): DRAM
I (518) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (524) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (531) heap_init: At 40099894 len 0000676C (25 KiB): IRAM
I (538) spi_flash: detected chip: generic
I (541) spi_flash: flash io: dio
W (545) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (560) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (569) MAIN: Size minimo de heap libre (antes de setup()): 225180 bytes
I (579) POWER_MGMT: Activando wakeup desde EXT1 con GPIO14
I (579) POWER_MGMT: Activando wakeup por ULP
I (639) MAIN: Size minimo de heap libre (despues de setup()): 222024 bytes
I (3639) BLE_DRIVER: Inicializando driver BLE
I (3639) BTDM_INIT: BT controller compile version [5688ed5]
I (3639) system_api: Base MAC address is not set
I (3639) MAIN: NVS inicializado
I (3639) system_api: read default base MAC address from EFUSE
I (3649) phy_init: phy_version 4670,719f9f6,Feb 18 2021,17:07:07
I (4089) GATT_SERVER: Attribute table created for service with UUID len = 16
I (4089) GATT_SERVER: Tabla GATT para HYDR_SVC creada, handle = 14
I (4099) GATT_SERVER: Attribute table created for service with UUID len = 2
I (4099) GATT_SERVER: Tabla GATT para BAT_SVC creada, handle = 4
I (4109) GATT_SERVER: Attribute table created for service with UUID len = 2
I (4119) GATT_SERVER: Tabla GATT para DEVICE_TIME_SVC creada, handle = 4
I (4129) GATT_SERVER: SERVICE_START_EVT, status 0, service_handle = 40
I (4129) GATT_SERVER: SERVICE_START_EVT, status 0, service_handle = 54
I (4139) GATT_SERVER: SERVICE_START_EVT, status 0, service_handle = 58
I (4149) BLE_GAP: Advertising comenzado
I (4649) BATTERY: eFuse Two Point: no soportado
I (4649) BATTERY: Characterized using eFuse Vref

I (4649) MAIN: HX711 sensor status (ESP_OK)
I (4659) MAIN: MPU6050 sensor status (ESP_ERR_TIMEOUT), device ID = 0     <---- PROBLEMA
I (4659) GATT_SERVER: ESP_GATTS_CONNECT_EVT, conn_id = 0
I (4659) MAIN: Battery monitor status (ESP_OK)
I (4669) GATT_SERVER: 44 85 bc cc 3d 8c
I (5009) MAIN: Lecturas de sensores: { raw_weight: 56118, volume: 120ml, accel: (0.00, 0.00, 0.00), gyro: (0.00, 0.00, 0.00), temp: 0.00, interval:0-0 ms}
I (5009) MAIN: Do measures represent hydration: no

[BUG] La conversión de números enteros a buffers de bytes necesita ser revisada

Descripción del Error
Los valores de los buffers de bytes usados para transmitir los registros de hidratación a través de BLE

Cómo Reproducir
Pasos para reproducir el error:

  1. Inicializar la extensión para botellas con la versión 1.0.0+2 programada en el ESP32.
  2. Emparejar un dispositivo móvil con la extensión, como dispositivo periférico.
  3. Observar los valores de los registros de hidratación generados semi-aleatoriamente.
  4. Observar los valores asignados a los atributos GATT de los servicios.

Comportamiento Esperado
La conversión de valores de tipo hydration_record_t a buffers de bytes para que sean sincronizados a través de BLE GATT debe ser revisada para asegurar que las representaciones en buffers sean correctas y puedan ser reconstruidas por la app.

Screenshots
Si aplican, agrega screenshots para ayudar a describir el problema.

Entorno

  • Módulo ESP-32: ESP-32
  • Versión de ESP-IDF: v4.4
  • Versión de software de aplicación: 1.0.0+2

Contexto Adicional
Por ejemplo, el siguiente hydration_record_t:

{ water: 518, temp: 33, bat: 78, time: 98}

Fue convertido a los buffers siguientes durante las pruebas:

{ water: [0XA1,0X3], temp: [0X10,0], bat: [0x, time: [0X2B,0,0,0]}

[BUG] La medición de voltaje de la batería es correcta, pero el porcentaje de carga restante calculado no

Descripción del Error
El servicio de monitoreo de carga de batería para el dispositivo produce mediciones de voltaje correctas, pero los valores usados en la tabla que describe la curva de carga característica no son correctos (usan voltajes absolutos, en el rango 3.0v - 4.2v, pero el ADC ajusta la escala de la medición realizada por la ESP32).

Cómo Reproducir
Pasos para reproducir el error:

  1. Conectar el dispositivo a puerto serial, para observar logs.
  2. Conectar la batería.
  3. Observar las mediciones de voltaje, típicamente en un rango de 2v.
  4. Notar que el voltaje incrementa con el tiempo, ya que el dispositivo está conectado a energía.
  5. Desconectar el cable USB que carga la batería.
  6. Esperar varios minutos.
  7. Re-conectar el dispositivo, notar que el voltaje medido es menor a las mediciones previas (el dispositivo estuvo usando poder de la batería).
  8. Observar que las mediciones son correctas, pero la conversión a porcentaje de carga no.

Comportamiento Esperado
El servicio de monitoreo de batería debería asociar cada medición de voltaje a un rango de porcentaje de carga correspondiente, descrito en la curva de carga característica.

Entorno

  • Módulo ESP-32: ESP32-WROOM-32E
  • Versión de ESP-IDF: v4.4.1
  • Versión de software de aplicación: 1.0.0+1

[FEATURE] Implementar el shutdown para el driver BLE

La funcionalidad que sugieres surgió de un problema? Por favor descríbelo.
Cuando la extensión para botellas activa su driver BLE, este se mantiene activo de forma indefinida, hasta que la extensión sea apagada o reiniciada. Sin embargo, en la implementación final será necesario activar y desactivar BLE según el estado de ahorro de energía de la extensión.

Describe la solución que te gustaría
El driver BLE debería proporcionar una API para manejar el shutdown con gracia del host de BLE, para que pueda hacer transición sin problema entre diversos estados y modos de operación.

Describe las alternativas que has considerado
Lo mejor posiblemente es crear algunas funciones que sean invocadas en dos situaciones:

  1. Al final de communication_task, antes de vTaskDelete(NULL).
  2. Después de determinar que la extensión debe entrar en modo de sueño ligero/profundo, antes de desactivar el chip.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.