├── .gitignore ├── AUTHORS.txt ├── BuildSysCMakeLib.cmake ├── CMakeLists.txt ├── ChangeLog.txt ├── LICENSE.txt ├── README.asciidoc ├── cmake_modules └── Findlibusb-1.0.cmake ├── doc ├── Doxyfile ├── logs │ ├── hem790it │ │ ├── 1_1_07_OneReading.html │ │ ├── 1_2_07_TwoReadings.html │ │ ├── 790IT_Cleared.html │ │ ├── 790IT_OneReading.html │ │ ├── 790IT_TwoReadings.html │ │ ├── Omron790IT.html │ │ ├── Omron790IT.ulz │ │ ├── new2 BP Report 042109.csv │ │ └── omron.mdb │ └── hj720it │ │ ├── pedometerData1.csv │ │ ├── pedometerData2.csv │ │ ├── pedometerData3.csv │ │ ├── pedometerLog1.xml │ │ ├── pedometerLog2.xml │ │ ├── pedometerLog3.xml │ │ ├── pedometerSniff1.usblog │ │ ├── pedometerSniff2.usblog │ │ └── pedometerSniff3.usblog └── omron_protocol_notes.asciidoc ├── examples ├── CMakeLists.txt ├── omron_720IT_test │ ├── omron_720IT_csv_dump.c │ └── omron_720IT_test.c └── omron_790IT_test │ └── omron_790IT_test.c ├── include ├── libomron │ └── omron.h └── win │ └── stdint.h ├── platform └── osx │ └── OmronNullDriver.kext │ └── Contents │ ├── Info.plist │ ├── Resources │ └── English.lproj │ │ └── InfoPlist.strings │ └── pbdevelopment.plist ├── python ├── CMakeLists.txt ├── __init__.py ├── device.py ├── gui.py ├── omron_790IT_test.py ├── plot.py └── store.py ├── src ├── CMakeLists.txt ├── omron.c ├── omron_libusb.c ├── omron_usbfs.c └── omron_win32.c └── swig ├── CMakeLists.txt ├── Omron.cxx ├── Omron.h └── omron.i /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.pyc 3 | *.sqlite3 4 | *.so 5 | *.out 6 | build* 7 | 8 | 9 | -------------------------------------------------------------------------------- /AUTHORS.txt: -------------------------------------------------------------------------------- 1 | Kyle Machulis 2 | kyle@nonpolynomial.com - http://www.nonpolynomial.com 3 | Brett Viren 4 | http://github.com/brettviren 5 | -------------------------------------------------------------------------------- /BuildSysCMakeLib.cmake: -------------------------------------------------------------------------------- 1 | ###################################################################################### 2 | # Add subdirectories 3 | ###################################################################################### 4 | 5 | # Add our repository cmake_modules directory 6 | LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake_modules) 7 | 8 | ###################################################################################### 9 | # Project Setup 10 | ###################################################################################### 11 | 12 | # ------------------------------------------------------------------------------ 13 | # INITIALIZE_BUILD is a beast of a macro that defines a lot of 14 | # defaults about what we expect to be in projects. Instead of 15 | # documenting all of the functionality here, I've added comment blocks 16 | # through the functions since it does so much. 17 | # ------------------------------------------------------------------------------ 18 | 19 | MACRO(INITIALIZE_BUILD) 20 | 21 | MACRO_ENSURE_OUT_OF_SOURCE_BUILD() 22 | 23 | # Set up default install directories if they aren't set for us 24 | IF(UNIX) 25 | IF(NOT CMAKE_INSTALL_PREFIX) 26 | SET(CMAKE_INSTALL_PREFIX /usr/local) 27 | ENDIF() 28 | ENDIF() 29 | 30 | IF(CMAKE_INSTALL_PREFIX) 31 | MESSAGE(STATUS "Installation Prefix: ${CMAKE_INSTALL_PREFIX}") 32 | ENDIF() 33 | 34 | # Set up defaults to look like "usr" format. We want all of our 35 | # projects in this layout. 36 | IF(NOT INCLUDE_INSTALL_DIR) 37 | SET(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include) 38 | ENDIF() 39 | IF(NOT LIBRARY_INSTALL_DIR) 40 | SET(LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib) 41 | ENDIF() 42 | IF(NOT RUNTIME_INSTALL_DIR) 43 | SET(RUNTIME_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/bin) 44 | ENDIF() 45 | IF(NOT SYMBOL_INSTALL_DIR) 46 | SET(SYMBOL_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/debug) 47 | ENDIF() 48 | IF(NOT DOC_INSTALL_DIR) 49 | SET(DOC_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/doc) 50 | ENDIF() 51 | IF(NOT FRAMEWORK_INSTALL_DIR) 52 | SET(FRAMEWORK_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/frameworks) 53 | ENDIF() 54 | IF(NOT CMAKE_MODULES_INSTALL_DIR) 55 | SET(CMAKE_MODULES_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/cmake_modules) 56 | ENDIF() 57 | 58 | SET(CMAKE_SKIP_BUILD_RPATH TRUE) 59 | SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) 60 | SET(CMAKE_INSTALL_RPATH "${LIBRARY_INSTALL_DIR}") 61 | SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 62 | 63 | # We always want to output our binaries and libraries to the same place, set that here 64 | SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin) 65 | SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) 66 | SET(DOC_OUTPUT_PATH ${CMAKE_BINARY_DIR}/doc) 67 | 68 | #Always assume we want to build threadsafe mingw binaries 69 | IF(MINGW) 70 | LIST(APPEND BUILDSYS_GLOBAL_DEFINES -mthreads) 71 | SET(CMAKE_LINK_FLAGS "${CMAKE_LINK_FLAGS} -mthreads") 72 | ENDIF() 73 | 74 | #defines we always need on gcc compilers 75 | IF(CMAKE_COMPILER_IS_GNUCXX) 76 | LIST(APPEND BUILDSYS_GLOBAL_DEFINES 77 | -DREENTRANT 78 | -D_REENTRANT 79 | -D_THREAD_SAFE 80 | -D_FILE_OFFSET_BITS=64 81 | -D_LARGEFILE_SOURCE 82 | ) 83 | ENDIF() 84 | 85 | IF(NOT MINGW) 86 | LIST(APPEND BUILDSYS_GLOBAL_DEFINES -D__STDC_LIMIT_MACROS) 87 | ENDIF() 88 | 89 | FOREACH(DEFINE ${BUILDSYS_GLOBAL_DEFINES}) 90 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DEFINE}") 91 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DEFINE}") 92 | ENDFOREACH(DEFINE ${BUILDSYS_GLOBAL_DEFINES}) 93 | 94 | #taken from OpenSceneGraph CMake. 95 | #Handy visual studio functions 96 | #Assuming /MP to always be on though 97 | IF(MSVC) 98 | 99 | # Fun with MSVC2010 linking 100 | # 101 | # As of VS2010, the "setting PREFIX to ../" hack no longer works 102 | # to avoid VS's injection of build types into the library output 103 | # path. Therefore, we have to set everything ourselves here. I 104 | # pulled this block from the OutDir test in the cmake source code, 105 | # because it's not really documented otherwise. 106 | # 107 | # Good times. 108 | 109 | if(CMAKE_CONFIGURATION_TYPES) 110 | foreach(config ${CMAKE_CONFIGURATION_TYPES}) 111 | string(TOUPPER "${config}" CONFIG) 112 | list(APPEND configs "${CONFIG}") 113 | endforeach() 114 | set(CMAKE_BUILD_TYPE) 115 | elseif(NOT CMAKE_BUILD_TYPE) 116 | set(CMAKE_BUILD_TYPE Debug) 117 | endif() 118 | 119 | # Now that we've gathered the configurations we're using, set them 120 | # all to the paths without the configuration type 121 | FOREACH(config ${configs}) 122 | SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${config} "${LIBRARY_OUTPUT_PATH}") 123 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${config} "${LIBRARY_OUTPUT_PATH}") 124 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config} "${EXECUTABLE_OUTPUT_PATH}") 125 | ENDFOREACH() 126 | 127 | # Check to see if we're using nmake. If so, set the NMAKE variable 128 | IF(CMAKE_MAKE_PROGRAM STREQUAL "nmake") 129 | SET(NMAKE 1) 130 | ENDIF() 131 | 132 | # Turn on PDB building 133 | OPTION(BUILDSYS_GLOBAL_INSTALL_PDB "When building DLLs or EXEs, always build and store a PDB file" OFF) 134 | 135 | # This option is to enable the /MP switch for Visual Studio 2005 and above compilers 136 | OPTION(WIN32_USE_MP "Set to ON to build with the /MP multiprocessor compile option (Visual Studio 2005 and above)." ON) 137 | IF(WIN32_USE_MP) 138 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") 139 | ENDIF() 140 | 141 | # More MSVC specific compilation flags 142 | ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS) 143 | ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE) 144 | 145 | #Assume we always want NOMINMAX defined, and lean and mean, 146 | #and no winsock1. Tends to throw redefinition warnings, but eh. 147 | ADD_DEFINITIONS(-DNOMINMAX -DWIN32_LEAN_AND_MEAN) 148 | ENDIF() 149 | 150 | IF(APPLE) 151 | SET(BUILDSYS_FRAMEWORKS) 152 | ENDIF() 153 | 154 | ENDMACRO(INITIALIZE_BUILD) 155 | 156 | ###################################################################################### 157 | # Parse Arguments Macro (for named argument building) 158 | ###################################################################################### 159 | 160 | #taken from http://www.cmake.org/Wiki/CMakeMacroParseArguments 161 | 162 | MACRO(PARSE_ARGUMENTS prefix arg_names option_names) 163 | SET(DEFAULT_ARGS) 164 | FOREACH(arg_name ${arg_names}) 165 | SET(${prefix}_${arg_name}) 166 | ENDFOREACH(arg_name) 167 | FOREACH(option ${option_names}) 168 | SET(${prefix}_${option} FALSE) 169 | ENDFOREACH(option) 170 | 171 | SET(current_arg_name DEFAULT_ARGS) 172 | SET(current_arg_list) 173 | FOREACH(arg ${ARGN}) 174 | SET(larg_names ${arg_names}) 175 | LIST(FIND larg_names "${arg}" is_arg_name) 176 | IF (is_arg_name GREATER -1) 177 | SET(${prefix}_${current_arg_name} ${current_arg_list}) 178 | SET(current_arg_name ${arg}) 179 | SET(current_arg_list) 180 | ELSE (is_arg_name GREATER -1) 181 | SET(loption_names ${option_names}) 182 | LIST(FIND loption_names "${arg}" is_option) 183 | IF (is_option GREATER -1) 184 | SET(${prefix}_${arg} TRUE) 185 | ELSE (is_option GREATER -1) 186 | LIST(APPEND current_arg_list ${arg}) 187 | ENDIF (is_option GREATER -1) 188 | ENDIF (is_arg_name GREATER -1) 189 | ENDFOREACH(arg) 190 | SET(${prefix}_${current_arg_name} ${current_arg_list}) 191 | ENDMACRO(PARSE_ARGUMENTS) 192 | 193 | ###################################################################################### 194 | # Compile flag array building macro 195 | ###################################################################################### 196 | 197 | #taken from http://www.cmake.org/pipermail/cmake/2006-February/008334.html 198 | 199 | MACRO(SET_COMPILE_FLAGS TARGET) 200 | SET(FLAGS) 201 | FOREACH(flag ${ARGN}) 202 | SET(FLAGS "${FLAGS} ${flag}") 203 | ENDFOREACH(flag) 204 | SET_TARGET_PROPERTIES(${TARGET} PROPERTIES COMPILE_FLAGS "${FLAGS}") 205 | ENDMACRO(SET_COMPILE_FLAGS) 206 | 207 | MACRO(SET_LINK_FLAGS TARGET) 208 | SET(FLAGS) 209 | FOREACH(flag ${ARGN}) 210 | SET(FLAGS "${FLAGS} ${flag}") 211 | ENDFOREACH(flag) 212 | SET_TARGET_PROPERTIES(${TARGET} PROPERTIES LINK_FLAGS "${FLAGS}") 213 | ENDMACRO(SET_LINK_FLAGS) 214 | 215 | ###################################################################################### 216 | # Generalized library building function for all C++ libraries 217 | ###################################################################################### 218 | 219 | # Function for building libraries 220 | # 221 | # All arguments are prefixed with BUILDSYS_LIB in the function 222 | # 223 | # Arguments 224 | # NAME - name of the library 225 | # SOURCES - list of sources to compile into library 226 | # CXX_FLAGS - flags to pass to the compiler 227 | # LINK_LIBS - libraries to link library to (dynamic libs only) 228 | # LINK_FLAGS - list of flags to use in linking (dynamic libs only) 229 | # DEPENDS - Targets that should be built before this target 230 | # LIB_TYPES_OVERRIDE - override the global types as set by OPTION_BUILD_STATIC/SHARED 231 | # SHOULD_INSTALL - should install commands be generated for this target? 232 | # VERSION - version number for library naming (non-windows dynamic libs only) 233 | # GROUP - Name of the compilation group this should be a part of (so you can build all of a group at once as a target) 234 | # EXCLUDE_FROM_ALL - Don't add as part of all target 235 | # 236 | # When finished, multiple targets are created 237 | # 238 | # - A target for building the library 239 | # -- [NAME]_[BUILD_TYPE] - i.e. for a static libfoo, there'd be a foo_STATIC target 240 | # - A target for setting dependencies on all versions of the library being built 241 | # -- [NAME]_DEPEND - i.e. foo_DEPEND, which will clear once foo_STATIC/SHARED is built 242 | # 243 | 244 | FUNCTION(BUILDSYS_BUILD_LIB) 245 | 246 | # Parse out the arguments 247 | PARSE_ARGUMENTS(BUILDSYS_LIB 248 | "NAME;SOURCES;CXX_FLAGS;LINK_LIBS;LINK_FLAGS;DEPENDS;LIB_TYPES_OVERRIDE;SHOULD_INSTALL;VERSION;GROUP;EXCLUDE_FROM_ALL;" 249 | "" 250 | ${ARGN} 251 | ) 252 | 253 | # Set up the types of library we want to build (STATIC, DYNAMIC, both) 254 | IF(BUILDSYS_LIB_LIB_TYPES_OVERRIDE) 255 | SET(BUILDSYS_LIB_TYPES_LIST ${BUILDSYS_LIB_LIB_TYPES_OVERRIDE}) 256 | ELSE() 257 | SET(BUILDSYS_LIB_TYPES_LIST ${BUILDSYS_LIB_TYPES}) 258 | ENDIF() 259 | 260 | # Remove all dupes from the source list, otherwise CMake freaks out 261 | LIST(REMOVE_DUPLICATES BUILDSYS_LIB_SOURCES) 262 | 263 | # Build each library type 264 | FOREACH(LIB_TYPE ${BUILDSYS_LIB_TYPES_LIST}) 265 | # Setup library name, targets, properties, etc... 266 | SET(CURRENT_LIB ${BUILDSYS_LIB_NAME}_${LIB_TYPE}) 267 | 268 | # To make sure we name our target correctly, but still link against the correct type 269 | IF(LIB_TYPE STREQUAL "FRAMEWORK") 270 | SET(TARGET_LIB_TYPE "SHARED") 271 | ELSE() 272 | SET(TARGET_LIB_TYPE ${LIB_TYPE}) 273 | ENDIF() 274 | 275 | IF(BUILDSYS_LIB_EXCLUDE_FROM_ALL) 276 | ADD_LIBRARY (${CURRENT_LIB} EXCLUDE_FROM_ALL ${TARGET_LIB_TYPE} ${BUILDSYS_LIB_SOURCES}) 277 | ELSE() 278 | ADD_LIBRARY (${CURRENT_LIB} ${TARGET_LIB_TYPE} ${BUILDSYS_LIB_SOURCES}) 279 | ENDIF() 280 | 281 | # Add this library to the list of all libraries we're building 282 | LIST(APPEND LIB_DEPEND_LIST ${CURRENT_LIB}) 283 | 284 | # This allows use to build static/shared libraries of the same name. 285 | # See http://www.itk.org/Wiki/CMake_FAQ#How_do_I_make_my_shared_and_static_libraries_have_the_same_root_name.2C_but_different_suffixes.3F 286 | IF(USE_STATIC_SUFFIX AND LIB_TYPE STREQUAL "STATIC") 287 | SET_TARGET_PROPERTIES (${CURRENT_LIB} PROPERTIES OUTPUT_NAME ${BUILDSYS_LIB_NAME}_s) 288 | ELSE() 289 | SET_TARGET_PROPERTIES (${CURRENT_LIB} PROPERTIES OUTPUT_NAME ${BUILDSYS_LIB_NAME}) 290 | ENDIF() 291 | SET_TARGET_PROPERTIES (${CURRENT_LIB} PROPERTIES CLEAN_DIRECT_OUTPUT 1) 292 | 293 | # Add version, if we're given one 294 | IF(BUILDSYS_LIB_VERSION) 295 | SET_TARGET_PROPERTIES (${CURRENT_LIB} PROPERTIES SOVERSION ${BUILDSYS_LIB_VERSION}) 296 | SET_TARGET_PROPERTIES (${CURRENT_LIB} PROPERTIES VERSION ${BUILDSYS_LIB_VERSION}) 297 | ENDIF() 298 | 299 | IF(LIB_TYPE STREQUAL "FRAMEWORK") 300 | SET_TARGET_PROPERTIES (${CURRENT_LIB} PROPERTIES FRAMEWORK 1) 301 | # As far as I can find, even in CMake 2.8.2, there's no way to 302 | # explictly copy header directories. This makes me sad. 303 | GET_TARGET_PROPERTY(OUT_LIB ${CURRENT_LIB} LOCATION) 304 | GET_FILENAME_COMPONENT(OUT_DIR ${OUT_LIB} PATH) 305 | MESSAGE(STATUS ${OUT_DIR}) 306 | ADD_CUSTOM_TARGET(${CURRENT_LIB}_FRAMEWORK_HEADER_COPY 307 | COMMAND "${CMAKE_COMMAND}" "-E" "make_directory" "${OUT_DIR}/Headers" 308 | COMMAND "${CMAKE_COMMAND}" "-E" "copy_directory" "${CMAKE_SOURCE_DIR}/include" "${OUT_DIR}/Headers" 309 | COMMAND "${CMAKE_COMMAND}" "-E" "create_symlink" "Versions/Current/Headers" "${OUT_DIR}/../../Headers") 310 | ADD_DEPENDENCIES(${CURRENT_LIB} ${CURRENT_LIB}_FRAMEWORK_HEADER_COPY) 311 | ENDIF() 312 | 313 | # Libraries we should link again 314 | IF(BUILDSYS_LIB_LINK_LIBS) 315 | TARGET_LINK_LIBRARIES(${CURRENT_LIB} ${BUILDSYS_LIB_LINK_LIBS}) 316 | ENDIF() 317 | 318 | # Defines and compiler flags, if any 319 | IF(BUILDSYS_LIB_CXX_FLAGS) 320 | SET_COMPILE_FLAGS(${CURRENT_LIB} ${BUILDSYS_LIB_CXX_FLAGS}) 321 | ENDIF() 322 | 323 | # Linker flags, if any 324 | IF(BUILDSYS_LIB_LINK_FLAGS) 325 | SET_LINK_FLAGS(${CURRENT_LIB} ${BUILDSYS_LIB_LINK_FLAGS}) 326 | ENDIF() 327 | 328 | # Installation commands 329 | IF(BUILDSYS_LIB_SHOULD_INSTALL AND NOT BUILDSYS_LIB_EXCLUDE_FROM_ALL) 330 | INSTALL(TARGETS ${CURRENT_LIB} LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR} ARCHIVE DESTINATION ${LIBRARY_INSTALL_DIR} FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}) 331 | ELSEIF(BUILDSYS_LIB_SHOULD_INSTALL AND BUILDSYS_LIB_EXCLUDE_FROM_ALL) 332 | # Only install the output file if it exists. This doesn't work for targets under exclude from all, but we may build them anyways 333 | MESSAGE(STATUS "NOTE: Target ${BUILDSYS_LIB_NAME} will only be installed after target is specifically built (not build using all target)") 334 | GET_TARGET_PROPERTY(LIB_OUTPUT_NAME ${CURRENT_LIB} LOCATION) 335 | INSTALL(FILES ${LIB_OUTPUT_NAME} LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR} ARCHIVE DESTINATION ${LIBRARY_INSTALL_DIR} OPTIONAL) 336 | ENDIF() 337 | 338 | # Rewrite of install_name_dir in apple binaries 339 | IF(APPLE) 340 | SET_TARGET_PROPERTIES(${CURRENT_LIB} PROPERTIES INSTALL_NAME_DIR ${LIBRARY_INSTALL_DIR}) 341 | ENDIF() 342 | 343 | 344 | # If the library depends on anything, set up dependency 345 | IF(BUILDSYS_LIB_DEPENDS) 346 | ADD_DEPENDENCIES(${CURRENT_LIB} ${BUILDSYS_LIB_DEPENDS}) 347 | ENDIF() 348 | 349 | ENDFOREACH() 350 | 351 | # Build the dependency name for ourselves and set up the target for it 352 | SET(DEPEND_NAME "${BUILDSYS_LIB_NAME}_DEPEND") 353 | ADD_CUSTOM_TARGET(${DEPEND_NAME} DEPENDS ${LIB_DEPEND_LIST}) 354 | 355 | IF(BUILDSYS_LIB_GROUP) 356 | IF(NOT TARGET ${BUILDSYS_LIB_GROUP}) 357 | MESSAGE(STATUS "Creating build group ${BUILDSYS_LIB_GROUP}") 358 | ADD_CUSTOM_TARGET(${BUILDSYS_LIB_GROUP} DEPENDS ${DEPEND_NAME}) 359 | ELSE() 360 | ADD_DEPENDENCIES(${BUILDSYS_LIB_GROUP} ${DEPEND_NAME}) 361 | ENDIF() 362 | ENDIF() 363 | 364 | ENDFUNCTION() 365 | 366 | ###################################################################################### 367 | # Generalized executable building function 368 | ###################################################################################### 369 | 370 | # Function for building executables 371 | # 372 | # All arguments are prefixed with BUILDSYS_EXE in the function 373 | # 374 | # Arguments 375 | # NAME - name of the executable 376 | # SOURCES - list of sources to compile into executable 377 | # CXX_FLAGS - flags to pass to the compiler 378 | # LINK_LIBS - libraries to link executable to 379 | # LINK_FLAGS - list of flags to use in linking 380 | # DEPENDS - Targets that should be built before this target 381 | # SHOULD_INSTALL - should install commands be generated for this target? 382 | # GROUP - Name of the compilation group this should be a part of (so you can build all of a group at once as a target) 383 | # EXCLUDE_FROM_ALL - Don't add as part of all target 384 | # INSTALL_PDB - On windows, if this is true, always create and install a PDB. Will also always happen with BUILDSYS_GLOBAL_INSTALL_PDB is on. 385 | # 386 | # When finished, one target is created, which is the NAME argument 387 | # 388 | 389 | FUNCTION(BUILDSYS_BUILD_EXE) 390 | PARSE_ARGUMENTS(BUILDSYS_EXE 391 | "NAME;SOURCES;CXX_FLAGS;LINK_LIBS;LINK_FLAGS;DEPENDS;SHOULD_INSTALL;GROUP;EXCLUDE_FROM_ALL;INSTALL_PDB;" 392 | "" 393 | ${ARGN} 394 | ) 395 | 396 | # Remove all dupes from the source list, otherwise CMake freaks out 397 | LIST(REMOVE_DUPLICATES BUILDSYS_EXE_SOURCES) 398 | 399 | # Create the target 400 | IF(BUILDSYS_EXE_EXCLUDE_FROM_ALL) 401 | ADD_EXECUTABLE(${BUILDSYS_EXE_NAME} EXCLUDE_FROM_ALL ${BUILDSYS_EXE_SOURCES}) 402 | ELSE() 403 | ADD_EXECUTABLE(${BUILDSYS_EXE_NAME} ${BUILDSYS_EXE_SOURCES}) 404 | ENDIF() 405 | SET_TARGET_PROPERTIES (${BUILDSYS_EXE_NAME} PROPERTIES OUTPUT_NAME ${BUILDSYS_EXE_NAME}) 406 | 407 | # Defines and compiler flags, if any 408 | IF(BUILDSYS_EXE_CXX_FLAGS) 409 | SET_COMPILE_FLAGS(${BUILDSYS_EXE_NAME} ${BUILDSYS_EXE_CXX_FLAGS}) 410 | ENDIF() 411 | 412 | # Set up rpaths to look in a few different places for libraries 413 | # - . (cwd) 414 | # - @loader_path/. (NOTE: @loader_path with no following path seems to fail) 415 | # - All of the library paths we linked again 416 | 417 | IF(NOT BUILDSYS_EXE_LINK_FLAGS) 418 | SET(BUILDSYS_EXE_LINK_FLAGS) 419 | ENDIF() 420 | 421 | IF(APPLE) 422 | # The three normal paths 423 | # Right next to us, in the path of the requesting binary, and @loader_path/../Frameworks (the bundle packing Frameworks version) 424 | LIST(APPEND BUILDSYS_EXE_LINK_FLAGS "-Wl,-rpath,@loader_path/." "-Wl,-rpath,@loader_path/../Frameworks" "-Wl,-rpath,.") 425 | IF(BUILDSYS_DEP_PATHS) 426 | FOREACH(PATH ${BUILDSYS_DEP_PATHS}) 427 | LIST(APPEND BUILDSYS_EXE_LINK_FLAGS "-Wl,-rpath,${PATH}/lib") 428 | ENDFOREACH() 429 | ENDIF() 430 | ENDIF() 431 | 432 | # If we're using Visual Studio, see whether or not we should 433 | # generate and install PDB files, even if we're in release 434 | IF(MSVC) 435 | IF(BUILDSYS_GLOBAL_INSTALL_PDB OR BUILDSYS_EXE_INSTALL_PDB) 436 | LIST(APPEND BUILDSYS_EXE_LINK_FLAGS "/DEBUG") 437 | GET_TARGET_PROPERTY(EXE_OUTPUT_NAME ${BUILDSYS_EXE_NAME} LOCATION) 438 | # Strip the .exe off the end and replace with .pdb 439 | STRING(REGEX REPLACE ".exe$" ".pdb" PDB_OUTPUT_NAME ${EXE_OUTPUT_NAME}) 440 | STRING(REGEX REPLACE "\\$\\(OutDir\\)" "" PDB_OUTPUT_NAME ${PDB_OUTPUT_NAME}) 441 | INSTALL(FILES ${PDB_OUTPUT_NAME} DESTINATION ${SYMBOL_INSTALL_DIR} OPTIONAL) 442 | ENDIF() 443 | ENDIF() 444 | 445 | # Linker flags, if any 446 | IF(BUILDSYS_EXE_LINK_FLAGS) 447 | SET_LINK_FLAGS(${BUILDSYS_EXE_NAME} ${BUILDSYS_EXE_LINK_FLAGS}) 448 | ENDIF() 449 | 450 | # Libraries to link to 451 | IF(BUILDSYS_EXE_LINK_LIBS) 452 | TARGET_LINK_LIBRARIES(${BUILDSYS_EXE_NAME} ${BUILDSYS_EXE_LINK_LIBS}) 453 | ENDIF() 454 | 455 | # Install commands 456 | IF(BUILDSYS_EXE_SHOULD_INSTALL AND NOT BUILDSYS_EXE_EXCLUDE_FROM_ALL) 457 | INSTALL(TARGETS ${BUILDSYS_EXE_NAME} RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR}) 458 | ELSEIF(BUILDSYS_EXE_SHOULD_INSTALL AND BUILDSYS_EXE_EXCLUDE_FROM_ALL) 459 | # Only install the output file if it exists. This doesn't work for targets under exclude from all, but we may build them anyways 460 | MESSAGE(STATUS "NOTE: Target ${BUILDSYS_EXE_NAME} will only be installed after target is specifically built (not build using all target)") 461 | GET_TARGET_PROPERTY(EXE_OUTPUT_NAME ${BUILDSYS_EXE_NAME} LOCATION) 462 | INSTALL(FILES ${EXE_OUTPUT_NAME} RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} OPTIONAL) 463 | ENDIF() 464 | 465 | 466 | # If the executable depends on anything, set up dependency 467 | IF(BUILDSYS_EXE_DEPENDS) 468 | ADD_DEPENDENCIES(${BUILDSYS_EXE_NAME} ${BUILDSYS_EXE_DEPENDS}) 469 | ENDIF() 470 | 471 | IF(BUILDSYS_EXE_GROUP) 472 | IF(NOT TARGET ${BUILDSYS_EXE_GROUP}) 473 | MESSAGE(STATUS "Creating build group ${BUILDSYS_EXE_GROUP}") 474 | ADD_CUSTOM_TARGET(${BUILDSYS_EXE_GROUP} DEPENDS ${BUILDSYS_EXE_NAME}) 475 | ELSE() 476 | ADD_DEPENDENCIES(${BUILDSYS_EXE_GROUP} ${BUILDSYS_EXE_NAME}) 477 | ENDIF() 478 | ENDIF() 479 | 480 | ENDFUNCTION(BUILDSYS_BUILD_EXE) 481 | 482 | ###################################################################################### 483 | # Make sure we aren't trying to do an in-source build 484 | ###################################################################################### 485 | 486 | #taken from http://www.mail-archive.com/cmake@cmake.org/msg14236.html 487 | 488 | MACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD) 489 | STRING(COMPARE EQUAL "${${PROJECT_NAME}_SOURCE_DIR}" "${${PROJECT_NAME}_BINARY_DIR}" insource) 490 | GET_FILENAME_COMPONENT(PARENTDIR ${${PROJECT_NAME}_SOURCE_DIR} PATH) 491 | STRING(COMPARE EQUAL "${${PROJECT_NAME}_SOURCE_DIR}" "${PARENTDIR}" insourcesubdir) 492 | IF(insource OR insourcesubdir) 493 | MESSAGE(FATAL_ERROR 494 | "${PROJECT_NAME} requires an out of source build (make a build dir and call cmake from that.)\n" 495 | "A script (Makefile or python) should've been included in your build to generate this, check your project root directory.\n" 496 | "If you get this error from a sub-directory, make sure there is not a CMakeCache.txt in your project root directory." 497 | ) 498 | ENDIF() 499 | ENDMACRO() 500 | 501 | ###################################################################################### 502 | # Create a library name that fits our platform 503 | ###################################################################################### 504 | 505 | MACRO(CREATE_LIBRARY_LINK_NAME LIBNAME) 506 | if(BUILD_STATIC AND NOT BUILD_SHARED) 507 | IF(NOT MSVC) 508 | SET(LIB_STATIC_PRE "lib") 509 | SET(LIB_STATIC_EXT ".a") 510 | ELSE(NOT MSVC) 511 | SET(LIB_STATIC_PRE "") 512 | SET(LIB_STATIC_EXT ".lib") 513 | ENDIF(NOT MSVC) 514 | SET(LIB_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH}/) 515 | ELSE(BUILD_STATIC AND NOT BUILD_SHARED) 516 | SET(LIB_STATIC_PRE) 517 | SET(LIB_STATIC_EXT) 518 | SET(LIB_OUTPUT_PATH) 519 | ENDIF(BUILD_STATIC AND NOT BUILD_SHARED) 520 | SET(lib${LIBNAME}_LIBRARY ${LIB_OUTPUT_PATH}${LIB_STATIC_PRE}${LIBNAME}${LIB_STATIC_EXT}) 521 | ENDMACRO(CREATE_LIBRARY_LINK_NAME) 522 | 523 | ###################################################################################### 524 | # Library Build Type Options 525 | ###################################################################################### 526 | 527 | MACRO(OPTION_LIBRARY_BUILD_STATIC DEFAULT) 528 | OPTION(BUILD_STATIC "Build static libraries" ${DEFAULT}) 529 | 530 | IF(BUILD_STATIC) 531 | LIST(APPEND BUILDSYS_LIB_TYPES STATIC) 532 | MESSAGE(STATUS "Building Static Libraries for ${CMAKE_PROJECT_NAME}") 533 | ELSE() 534 | MESSAGE(STATUS "NOT Building Static Libraries for ${CMAKE_PROJECT_NAME}") 535 | ENDIF() 536 | ENDMACRO() 537 | 538 | MACRO(OPTION_USE_STATIC_SUFFIX DEFAULT) 539 | OPTION(USE_STATIC_SUFFIX "If building static libraries, suffix their name with _s. Handy on windows when building both." ${DEFAULT}) 540 | 541 | IF(USE_STATIC_SUFFIX) 542 | MESSAGE(STATUS "Building Static Libraries with suffix '_s'") 543 | ELSE() 544 | MESSAGE(STATUS "Building Static Libraries with same name as shared (may cause issues on windows)") 545 | ENDIF() 546 | ENDMACRO() 547 | 548 | MACRO(OPTION_LIBRARY_BUILD_SHARED DEFAULT) 549 | OPTION(BUILD_SHARED "Build shared libraries" ${DEFAULT}) 550 | 551 | IF(BUILD_SHARED) 552 | LIST(APPEND BUILDSYS_LIB_TYPES SHARED) 553 | MESSAGE(STATUS "Building Shared Libraries for ${CMAKE_PROJECT_NAME}") 554 | ELSE() 555 | MESSAGE(STATUS "NOT Building Shared Libraries for ${CMAKE_PROJECT_NAME}") 556 | ENDIF() 557 | ENDMACRO() 558 | 559 | MACRO(OPTION_LIBRARY_BUILD_FRAMEWORK DEFAULT) 560 | IF(APPLE) 561 | OPTION(BUILD_FRAMEWORK "Build OS X Frameworks" ${DEFAULT}) 562 | 563 | IF(BUILD_FRAMEWORK) 564 | LIST(APPEND BUILDSYS_LIB_TYPES FRAMEWORK) 565 | MESSAGE(STATUS "Building Shared Libraries for ${CMAKE_PROJECT_NAME}") 566 | ELSE() 567 | MESSAGE(STATUS "NOT Building Shared Libraries for ${CMAKE_PROJECT_NAME}") 568 | ENDIF() 569 | ENDIF() 570 | ENDMACRO() 571 | 572 | ###################################################################################### 573 | # RPATH Relink Options 574 | ###################################################################################### 575 | 576 | MACRO(OPTION_BUILD_RPATH DEFAULT) 577 | OPTION(SET_BUILD_RPATH "Set the build RPATH to local directories, relink to install directories at install time" ${DEFAULT}) 578 | 579 | IF(SET_BUILD_RPATH) 580 | MESSAGE(STATUS "Setting build RPATH for ${CMAKE_PROJECT_NAME}") 581 | # use, i.e. don't skip the full RPATH for the build tree 582 | SET(CMAKE_SKIP_BUILD_RPATH FALSE) 583 | 584 | # when building, don't use the install RPATH already 585 | # (but later on when installing) 586 | SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) 587 | 588 | # the RPATH to be used when installing 589 | SET(CMAKE_INSTALL_RPATH "${LIBRARY_INSTALL_DIR}") 590 | 591 | # add the automatically determined parts of the RPATH 592 | # which point to directories outside the build tree to the install RPATH 593 | SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 594 | ELSE() 595 | MESSAGE(STATUS "NOT Setting build RPATH for ${CMAKE_PROJECT_NAME}") 596 | ENDIF() 597 | ENDMACRO() 598 | 599 | ###################################################################################### 600 | # Create software version code file 601 | ###################################################################################### 602 | 603 | MACRO(OPTION_CREATE_VERSION_FILE DEFAULT OUTPUT_FILES) 604 | OPTION(CREATE_VERSION_FILE "Creates a version.cc file using the setlocalversion script" ${DEFAULT}) 605 | IF(CREATE_VERSION_FILE) 606 | MESSAGE(STATUS "Generating git information for ${CMAKE_PROJECT_NAME}") 607 | FOREACH(VERSION_FILE ${OUTPUT_FILES}) 608 | MESSAGE(STATUS "- Generating to ${VERSION_FILE}") 609 | SET(COMMAND_LIST "python" "${BUILDSYS_CMAKE_DIR}/../python/get_version.py" "-f" "${VERSION_FILE}" "-d" "${CMAKE_SOURCE_DIR}") 610 | EXECUTE_PROCESS(COMMAND ${COMMAND_LIST}) 611 | ENDFOREACH(VERSION_FILE ${OUTPUT_FILES}) 612 | ELSE() 613 | MESSAGE(STATUS "NOT generating git information for ${CMAKE_PROJECT_NAME}") 614 | ENDIF() 615 | ENDMACRO() 616 | 617 | ###################################################################################### 618 | # Turn on GProf based profiling 619 | ###################################################################################### 620 | 621 | MACRO(OPTION_GPROF DEFAULT) 622 | IF(CMAKE_COMPILER_IS_GNUCXX) 623 | OPTION(ENABLE_GPROF "Compile using -g -pg for gprof output" ${DEFAULT}) 624 | IF(ENABLE_GPROF) 625 | MESSAGE(STATUS "Using gprof output for ${CMAKE_PROJECT_NAME}") 626 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -pg") 627 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -pg") 628 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g -pg") 629 | SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g -pg") 630 | ELSE() 631 | MESSAGE(STATUS "NOT using gprof output for ${CMAKE_PROJECT_NAME}") 632 | ENDIF() 633 | ELSE() 634 | MESSAGE(STATUS "gprof generation NOT AVAILABLE - Not a GNU compiler") 635 | ENDIF() 636 | ENDMACRO() 637 | 638 | ###################################################################################### 639 | # Turn on "extra" compiler warnings (SPAMMY WITH BOOST) 640 | ###################################################################################### 641 | 642 | MACRO(OPTION_EXTRA_COMPILER_WARNINGS DEFAULT) 643 | IF(CMAKE_COMPILER_IS_GNUCXX) 644 | OPTION(EXTRA_COMPILER_WARNINGS "Turn on -Wextra for gcc" ${DEFAULT}) 645 | IF(EXTRA_COMPILER_WARNINGS) 646 | MESSAGE(STATUS "Turning on extra c/c++ warnings for ${CMAKE_PROJECT_NAME}") 647 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra") 648 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") 649 | ELSE() 650 | MESSAGE(STATUS "NOT turning on extra c/c++ warnings for ${CMAKE_PROJECT_NAME}") 651 | ENDIF() 652 | ELSE() 653 | MESSAGE(STATUS "Extra compiler warnings NOT AVAILABLE - Not a GNU compiler") 654 | ENDIF() 655 | ENDMACRO() 656 | 657 | ###################################################################################### 658 | # Turn on effective C++ compiler warnings 659 | ###################################################################################### 660 | 661 | MACRO(OPTION_EFFCXX_COMPILER_WARNINGS DEFAULT) 662 | IF(CMAKE_COMPILER_IS_GNUCXX) 663 | OPTION(EFFCXX_COMPILER_WARNINGS "Turn on -Weffc++ (effective c++ warnings) for gcc" ${DEFAULT}) 664 | IF(EFFCXX_COMPILER_WARNINGS) 665 | MESSAGE(STATUS "Turning on Effective c++ warnings for ${CMAKE_PROJECT_NAME}") 666 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weffc++") 667 | ELSE() 668 | MESSAGE(STATUS "NOT turning on Effective c++ warnings for ${CMAKE_PROJECT_NAME}") 669 | ENDIF() 670 | ELSE() 671 | MESSAGE(STATUS "Effective C++ compiler warnings NOT AVAILABLE - Not a GNU compiler") 672 | ENDIF() 673 | ENDMACRO() 674 | 675 | ###################################################################################### 676 | # Return type compiler warnings 677 | ###################################################################################### 678 | 679 | MACRO(OPTION_RETURN_TYPE_COMPILER_WARNINGS DEFAULT) 680 | IF(CMAKE_COMPILER_IS_GNUCXX) 681 | OPTION(RETURN_TYPE_COMPILER_WARNINGS "Turn on -Wreturn-type for gcc" ${DEFAULT}) 682 | IF(RETURN_TYPE_COMPILER_WARNINGS) 683 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wreturn-type") 684 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wreturn-type") 685 | MESSAGE(STATUS "Turning on return type warnings for ${CMAKE_PROJECT_NAME}") 686 | ELSE() 687 | MESSAGE(STATUS "NOT turning on return type warnings for ${CMAKE_PROJECT_NAME}") 688 | ENDIF() 689 | ELSE() 690 | MESSAGE(STATUS "Return type warnings NOT AVAILABLE - Not a GNU compiler") 691 | ENDIF() 692 | ENDMACRO() 693 | 694 | ###################################################################################### 695 | # Force 32-bit, regardless of the platform we're on 696 | ###################################################################################### 697 | 698 | MACRO(OPTION_FORCE_32_BIT DEFAULT) 699 | IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") 700 | IF(CMAKE_COMPILER_IS_GNUCXX) 701 | OPTION(FORCE_32_BIT "Force compiler to use -m32 when compiling" ${DEFAULT}) 702 | IF(FORCE_32_BIT) 703 | MESSAGE(STATUS "Forcing 32-bit on 64-bit platform (using -m32)") 704 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") 705 | SET(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -m32") 706 | SET(CMAKE_LINK_FLAGS "${CMAKE_CXX_FLAGS} -m32") 707 | ELSE() 708 | MESSAGE(STATUS "Not forcing 32-bit on 64-bit platform") 709 | ENDIF() 710 | ELSE() 711 | MESSAGE(STATUS "Force 32 bit NOT AVAILABLE - Not using gnu compiler") 712 | ENDIF() 713 | ELSE({CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") 714 | MESSAGE(STATUS "Force 32 bit NOT AVAILABLE - Already on a 32 bit platform") 715 | ENDIF() 716 | ENDMACRO() 717 | 718 | ###################################################################################### 719 | # Uninstall function 720 | # From http://www.cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F 721 | ###################################################################################### 722 | 723 | # IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 724 | # MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") 725 | # ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 726 | 727 | # FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) 728 | # STRING(REGEX REPLACE "\n" ";" files "${files}") 729 | # FOREACH(file ${files}) 730 | # MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") 731 | # IF(EXISTS "$ENV{DESTDIR}${file}") 732 | # EXEC_PROGRAM( 733 | # "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 734 | # OUTPUT_VARIABLE rm_out 735 | # RETURN_VALUE rm_retval 736 | # ) 737 | # IF(NOT "${rm_retval}" STREQUAL 0) 738 | # MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") 739 | # ENDIF(NOT "${rm_retval}" STREQUAL 0) 740 | # ELSE(EXISTS "$ENV{DESTDIR}${file}") 741 | # MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") 742 | # ENDIF(EXISTS "$ENV{DESTDIR}${file}") 743 | # ENDFOREACH(file) 744 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ###################################################################################### 2 | # CMake directives 3 | ###################################################################################### 4 | 5 | #Require 2.6 or higher. 6 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR) 7 | 8 | INCLUDE( ${CMAKE_SOURCE_DIR}/BuildSysCMakeLib.cmake ) 9 | 10 | #setting link directory policy 11 | IF(COMMAND cmake_policy) 12 | CMAKE_POLICY(SET CMP0003 NEW) 13 | ENDIF(COMMAND cmake_policy) 14 | 15 | ###################################################################################### 16 | # Project declaration and options 17 | ###################################################################################### 18 | 19 | #Project declaration 20 | 21 | PROJECT(LIBOMRON) 22 | 23 | # Project initialization 24 | INITIALIZE_BUILD() 25 | 26 | #Common Options 27 | 28 | OPTION_LIBRARY_BUILD_STATIC(ON) 29 | OPTION_LIBRARY_BUILD_SHARED(ON) 30 | IF(WIN32) 31 | OPTION_USE_STATIC_SUFFIX(ON) 32 | ENDIF() 33 | IF(APPLE) 34 | OPTION_LIBRARY_BUILD_FRAMEWORK(OFF) 35 | ENDIF() 36 | OPTION_BUILD_RPATH(ON) 37 | 38 | ###################################################################################### 39 | # Project specific globals 40 | ###################################################################################### 41 | 42 | #library definitions 43 | 44 | SET(LIBOMRON_MAJOR_VERSION 0) 45 | SET(LIBOMRON_MINOR_VERSION 9) 46 | SET(LIBOMRON_BUILD_VERSION 0) 47 | 48 | SET(LIBOMRON_VERSION ${LIBOMRON_MAJOR_VERSION}.${LIBOMRON_MINOR_VERSION}.${LIBOMRON_BUILD_VERSION}) 49 | 50 | CREATE_LIBRARY_LINK_NAME("omron") 51 | 52 | # Just set our include and linking directories globally 53 | INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) 54 | LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/lib) 55 | 56 | #library name definitions 57 | SET(LIBOMRON_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/include") 58 | SET(LIBOMRON_REQUIRED_LIBS) 59 | 60 | IF(WIN32) 61 | SET(WDK_PATH CACHE PATH "Path to WDK Installation") 62 | INCLUDE_DIRECTORIES(${WDK_PATH}/inc/api ${WDK_PATH}/inc/crt ${WDK_PATH}/inc) 63 | LINK_DIRECTORIES(${WDK_PATH}/lib/wxp/i386) 64 | LIST(APPEND LIBOMRON_REQUIRED_LIBS hid setupapi) 65 | INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/win) 66 | ELSEIF(UNIX) 67 | FIND_PACKAGE(libusb-1.0 REQUIRED) 68 | IF(LIBUSB_1_FOUND) 69 | INCLUDE_DIRECTORIES(${LIBUSB_1_INCLUDE_DIRS}) 70 | LIST(APPEND LIBOMRON_REQUIRED_LIBS ${LIBUSB_1_LIBRARIES}) 71 | ENDIF(LIBUSB_1_FOUND) 72 | ENDIF(WIN32) 73 | 74 | ###################################################################################### 75 | # Installation of headers 76 | ###################################################################################### 77 | 78 | SET(LIBOMRON_INCLUDE_DIRS 79 | ${CMAKE_CURRENT_SOURCE_DIR}/include/libomron 80 | ) 81 | 82 | INSTALL(DIRECTORY 83 | ${LIBOMRON_INCLUDE_DIRS} 84 | DESTINATION ${INCLUDE_INSTALL_DIR}/libomron 85 | ) 86 | 87 | FOREACH(DIR ${LIBOMRON_INCLUDE_DIRS}) 88 | FILE(GLOB_RECURSE HEADER_FILES ${DIR}/*.h) 89 | LIST(APPEND LIBOMRON_INCLUDE_FILES ${HEADER_FILES}) 90 | ENDFOREACH(DIR ${LIBOMRON_INCLUDE_DIRS}) 91 | 92 | IF(BUILD_SHARED AND WIN32) 93 | ADD_DEFINITIONS(-DOMRON_DYNAMIC) 94 | ENDIF() 95 | 96 | ###################################################################################### 97 | # Subdirectories 98 | ###################################################################################### 99 | 100 | ADD_SUBDIRECTORY(src) 101 | ADD_SUBDIRECTORY(examples) 102 | ADD_SUBDIRECTORY(swig) 103 | ADD_SUBDIRECTORY(python) 104 | -------------------------------------------------------------------------------- /ChangeLog.txt: -------------------------------------------------------------------------------- 1 | libomron ChangeLog 2 | ===================== 3 | Numbers refer to bug listings for libomron bug tracking system - https://github.com/qdot/libomron/issues 4 | 5 | 2010-12-31 Kyle Machulis 6 | * Release v0.9.0 7 | * First release, but comes with support for 720-compatible Pedometers and 790-IT-compatible BP Monitors on windows/linux/mac 8 | * Includes SWIG and Python library (Thanks to Brett Viren) 9 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2010, Kyle Machulis/Nonpolynomial Labs 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the Kyle Machulis/Nonpolynomial Labs nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY Kyle Machulis/Nonpolynomial Labs ''AS IS'' AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL Kyle Machulis/Nonpolynomial Labs BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE 25 | -------------------------------------------------------------------------------- /README.asciidoc: -------------------------------------------------------------------------------- 1 | = libomron = 2 | 3 | by Kyle Machulis 4 | 5 | Nonpolynomial Labs - http://www.nonpolynomial.com 6 | 7 | with contributions from 8 | 9 | * Brett Viren - SWIG Implementaiton, Python utils 10 | * And others 11 | 12 | If you find libomron useful, please donate to the project at http://www.pledgie.com/campaigns/14372 13 | 14 | == Description == 15 | 16 | libomron is a mainly C-based implementation of the data retreival 17 | protocol for the USB enabled line of omron home medical 18 | equipment. 19 | 20 | == Supported Hardware == 21 | 22 | _Blood Pressure Monitors_ 23 | * HEM-790-IT 24 | * BP-791-IT 25 | * M10-IT 26 | 27 | _Pedometers_ 28 | * HJ-720-IT 29 | 30 | While basic communication functions in the library should work for any 31 | Omron product, there may be differences in packet layout and measure 32 | units between US/European/Japanese/etc products... We will try to 33 | cover these as requested, but the library itself is produced in the 34 | US, so that's what I have easiest access to. 35 | 36 | == Package Information == 37 | 38 | Project Information @ http://libomron.nonpolynomial.com 39 | 40 | Source repo @ http://www.github.com/qdot/libomron 41 | 42 | Releases @ http://www.sourceforge.net/projects/nplabs 43 | 44 | == A Tale of Two Libraries == 45 | 46 | libomron comes in two flavors: Win32 and libusb-1.0. The Win32 version 47 | uses direct Win32 DDK calls to access the windows HID system, and 48 | reads raw reports from there (which means we aren't required to 49 | install any specific drivers.). libusb-1.0 works for all platforms 50 | currently supporting the library. 51 | 52 | == Library Requirements (For Compilation) == 53 | 54 | * CMake (Required on all platforms) - http://www.cmake.org 55 | * SWIG (For non-C libraries) - http://www.swig.org 56 | * Python (with dev libraries, for python lib) - http://www.python.org 57 | * WDK (Windows Only) - http://www.microsoft.com/whdc/devtools/WDK/default.mspx 58 | * libusb-1.0 (All non-windows platforms) - http://www.libusb.org 59 | 60 | To build on Ubuntu, you can pull the following packages to build the 61 | project from source. 62 | 63 | * libusb-1.0-0-dev 64 | * cmake 65 | * cmake-data 66 | 67 | For OS X, there are build files available for homebrew and macports. 68 | 69 | == Build Notes == 70 | 71 | To build libomron, make a subdirectory in the source dir (called 72 | whatever you want), then go into that directory and run 73 | "cmake ..". This will generate the project files for your platform 74 | (makefiles for OS X and linux, visual studio for windows). For more 75 | information on project generators, look at the cmake documentation. 76 | 77 | == Notes on Compilation and Usage == 78 | 79 | === Mac OS X === 80 | 81 | You will need to install the "Omron OS X Extension" in order to use 82 | omron software on OS X. The file and installation instructions are 83 | available on the libomron sourceforge site, or in the mac binary 84 | package if one is available. The kext should work on 10.5 or later. 85 | 86 | === Linux === 87 | 88 | The VID/PID pair of the omron will need to be blacklisted on linux in 89 | order to use libomron there without requiring root access. This can be 90 | done either in the kernel or through udev. 91 | 92 | == License == 93 | 94 | --------------------- 95 | Copyright (c) 2009-2010, Kyle Machulis/Nonpolynomial Labs 96 | All rights reserved. 97 | 98 | Redistribution and use in source and binary forms, with or without 99 | modification, are permitted provided that the following conditions are met: 100 | * Redistributions of source code must retain the above copyright 101 | notice, this list of conditions and the following disclaimer. 102 | * Redistributions in binary form must reproduce the above copyright 103 | notice, this list of conditions and the following disclaimer in the 104 | documentation and/or other materials provided with the distribution. 105 | * Neither the name of the Kyle Machulis/Nonpolynomial Labs nor the 106 | names of its contributors may be used to endorse or promote products 107 | derived from this software without specific prior written permission. 108 | 109 | THIS SOFTWARE IS PROVIDED BY Kyle Machulis/Nonpolynomial Labs ''AS IS'' AND ANY 110 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 111 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 112 | DISCLAIMED. IN NO EVENT SHALL Kyle Machulis/Nonpolynomial Labs BE LIABLE FOR ANY 113 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 114 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 115 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 116 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 117 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 118 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE 119 | --------------------- 120 | 121 | == Brett Viren's README == 122 | 123 | (I'm including Brett's README here because I'm too lazy to integrate 124 | it and just want to get 0.9.0 out. :) ) 125 | 126 | This is a fork of http://github.com/qdot/libomron I use to play around 127 | with my 790-IT. Much thanks to qDot for the original heavy lifting! 128 | The intention here is to scratch my own itch and feed any useful 129 | improvements back to qDot. 130 | 131 | * Overview 132 | 133 | This fork adds: 134 | 135 | * Python bindings via SWIG 136 | 137 | * Python utilities including plotting, device autodetection 138 | 139 | * Random bug fixes/improvements on the C side 140 | 141 | * A simple Python/TK GUI app. 142 | 143 | * Installation 144 | 145 | ** Pre-requirements 146 | 147 | * CMake 148 | 149 | * SWIG 150 | 151 | ** Steps for installation, testing and running 152 | 153 | Things are not as polished as they could be, but here is how to go 154 | from nothing to something. 155 | 156 | It assumes these locations: 157 | 158 | - git clone to ~/git/libomron 159 | - build area in ~/opt/omron-build 160 | - install area in ~/opt/omron 161 | 162 | 0) Clone github repo by going to http://github.com/brettviren/libomron 163 | and selecting a method 164 | 165 | cd ~/git 166 | git clone ... 167 | 168 | 1) Go to resulting libomron/ directory and install needed qDot 169 | submodule (git://github.com/qdot/compily_buildd.git) 170 | 171 | cd ~/git/libomron 172 | git submodule update --init 173 | 174 | 2) Create and enter installation directory 175 | 176 | mkdir -p ~/opt/omron-build 177 | cd ~/opt/omron-build/ 178 | 179 | 3) Run "cmake ~/git/libomron" 180 | 181 | 4) Run "make" and optionally "make DESTDIR=~/opt/omron install" 182 | 183 | 5) Plug in USB and find out device 184 | 185 | lsusb | grep Omron 186 | Bus 005 Device 006: ID 0590:0028 Omron Corp. HJ-720IT Pedometer 187 | 188 | (note, my 790-IT blood pressure monitor is identified incorectly, but 189 | that is okay) 190 | 191 | 6) From the numbers above, set this env. var.: 192 | 193 | export OMRON_DEV=/dev/bus/usb/005/006 194 | 195 | 7) Check that it is readable and writable by you: 196 | 197 | ls -l $OMRON_DEV 198 | groups 199 | 200 | 8) Finally, run the example to readout stored values 201 | 202 | ~/opt/omron/usr/local/bin/omron_790IT_test 203 | 204 | 9) Try out the python bindings do: 205 | 206 | export PYTHONPATH=~/opt/omron/usr/local/python 207 | python ~/opt/omron/usr/local/python/omron/omron_790IT_test.py 208 | # (this will make a omron.sqlite3 in current directory 209 | python ~/opt/omron/usr/local/python/omron/store.py 210 | # (this will dump omron.sqlite3) 211 | python ~/opt/omron/usr/local/python/omron/plot.py 212 | # (this wlil plot all readouts) 213 | 214 | 10) Try the GUI app 215 | 216 | # Set PYTHONPATH as above, and print help screen 217 | python ~/opt/omron/usr/local/python/omron/gui -h 218 | # Run it, point it to a data file, can be same one produced above 219 | python ~/opt/omron/usr/local/python/omron/gui -f omron.sqlite3 220 | -------------------------------------------------------------------------------- /cmake_modules/Findlibusb-1.0.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find libusb-1.0 2 | # Once done this will define 3 | # 4 | # LIBUSB_1_FOUND - system has libusb 5 | # LIBUSB_1_INCLUDE_DIRS - the libusb include directory 6 | # LIBUSB_1_LIBRARIES - Link these to use libusb 7 | # LIBUSB_1_DEFINITIONS - Compiler switches required for using libusb 8 | # 9 | # Adapted from cmake-modules Google Code project 10 | # 11 | # Copyright (c) 2006 Andreas Schneider 12 | # 13 | # (Changes for libusb) Copyright (c) 2008 Kyle Machulis 14 | # 15 | # Redistribution and use is allowed according to the terms of the New BSD license. 16 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 17 | # 18 | 19 | 20 | if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) 21 | # in cache already 22 | set(LIBUSB_FOUND TRUE) 23 | else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) 24 | find_path(LIBUSB_1_INCLUDE_DIR 25 | NAMES 26 | libusb-1.0/libusb.h 27 | PATHS 28 | /usr/include 29 | /usr/local/include 30 | /opt/local/include 31 | /sw/include 32 | PATH_SUFFIXES 33 | libusb-1.0 34 | ) 35 | 36 | find_library(LIBUSB_1_LIBRARY 37 | NAMES 38 | usb-1.0 39 | PATHS 40 | /usr/lib 41 | /usr/local/lib 42 | /opt/local/lib 43 | /sw/lib 44 | ) 45 | 46 | set(LIBUSB_1_INCLUDE_DIRS 47 | ${LIBUSB_1_INCLUDE_DIR} 48 | ) 49 | set(LIBUSB_1_LIBRARIES 50 | ${LIBUSB_1_LIBRARY} 51 | ) 52 | 53 | if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES) 54 | set(LIBUSB_1_FOUND TRUE) 55 | endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES) 56 | 57 | if (LIBUSB_1_FOUND) 58 | if (NOT libusb_1_FIND_QUIETLY) 59 | message(STATUS "Found libusb-1.0:") 60 | message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}") 61 | message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}") 62 | endif (NOT libusb_1_FIND_QUIETLY) 63 | else (LIBUSB_1_FOUND) 64 | if (libusb_1_FIND_REQUIRED) 65 | message(FATAL_ERROR "Could not find libusb") 66 | endif (libusb_1_FIND_REQUIRED) 67 | endif (LIBUSB_1_FOUND) 68 | 69 | # show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view 70 | mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES) 71 | 72 | endif (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) -------------------------------------------------------------------------------- /doc/logs/hem790it/Omron790IT.ulz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qdot/libomron/2687b382eac0faaa7de0f2727fc77c22514f053c/doc/logs/hem790it/Omron790IT.ulz -------------------------------------------------------------------------------- /doc/logs/hem790it/new2 BP Report 042109.csv: -------------------------------------------------------------------------------- 1 | new2,, 2 | 3 | Date,Time,SYS (mmHg),DIA (mmHg),Pulse (Pulses/min),Irregular Heartbeat (y or n),Excessive Movement (y or n),Memo (y or n),MsCnt1,MsCnt2,MsCnt3,InputType,MeasureType,Comment 4 | 1/01/2007,12:06:38 AM,123,78,87,n,n,n,0,0,0,0,2, 5 | 1/02/2007,12:08:38 AM,120,73,67,n,n,n,0,0,0,0,2, 6 | -------------------------------------------------------------------------------- /doc/logs/hem790it/omron.mdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qdot/libomron/2687b382eac0faaa7de0f2727fc77c22514f053c/doc/logs/hem790it/omron.mdb -------------------------------------------------------------------------------- /doc/logs/hj720it/pedometerData1.csv: -------------------------------------------------------------------------------- 1 | Kato,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 2 | ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 3 | Date,Total Steps,Aerobic Steps,Aerobic Walking Time,Calories,Distance,Fat Burned,Steps 12AM,Steps 1AM,Steps 2AM,Steps 3AM,Steps 4AM,Steps 5AM,Steps 6AM,Steps 7AM,Steps 8AM,Steps 9AM,Steps 10AM,Steps 11AM,Steps 12PM,Steps 1PM,Steps 2PM,Steps 3PM,Steps 4PM,Steps 5PM,Steps 6PM,Steps 7PM,Steps 8PM,Steps 9PM,Steps 10PM,Steps 11PM,Aerobic Steps 12AM,Aerobic Steps 1AM,Aerobic Steps 2AM,Aerobic Steps 3AM,Aerobic Steps 4AM,Aerobic Steps 5AM,Aerobic Steps 6AM,Aerobic Steps 7AM,Aerobic Steps 8AM,Aerobic Steps 9AM,Aerobic Steps 10AM,Aerobic Steps 11AM,Aerobic Steps 12PM,Aerobic Steps 1PM,Aerobic Steps 2PM,Aerobic Steps 3PM,Aerobic Steps 4PM,Aerobic Steps 5PM,Aerobic Steps 6PM,Aerobic Steps 7PM,Aerobic Steps 8PM,Aerobic Steps 9PM,Aerobic Steps 10PM,Aerobic Steps 11PM,Used 12AM,Used 1AM,Used 2AM,Used 3AM,Used 4AM,Used 5AM,Used 6AM,Used 7AM,Used 8AM,Used 9AM,Used 10AM,Used 11AM,Used 12PM,Used 1PM,Used 2PM,Used 3PM,Used 4PM,Used 5PM,Used 6PM,Used 7PM,Used 8PM,Used 9PM,Used 10PM,Used 11PM,Event 12AM,Event 1AM,Event 2AM,Event 3AM,Event 4AM,Event 5AM,Event 6AM,Event 7AM,Event 8AM,Event 9AM,Event 10AM,Event 11AM,Event 12PM,Event 1PM,Event 2PM,Event 3PM,Event 4PM,Event 5PM,Event 6PM,Event 7PM,Event 8PM,Event 9PM,Event 10PM,Event 11PM 4 | 5/14/2009,3268,2898,20,124,1.65,7.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,81,0,1747,1322,20,90,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1670,1228,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 5 | 5/15/2009,5251,3426,24,186,2.65,11.1,0,0,0,0,0,0,0,256,126,94,273,473,338,33,0,0,14,90,3515,39,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3426,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 6 | 5/16/2009,8348,5027,42,308,4.21,18.4,0,0,0,0,0,0,0,142,6151,727,726,7,0,0,0,121,40,236,42,156,0,0,0,0,0,0,0,0,0,0,0,0,4522,505,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 7 | 5/17/2009,2902,0,0,96,1.46,5.2,0,0,0,0,0,0,0,0,0,182,1345,105,559,582,0,0,0,79,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 8 | 5/18/2009,1042,0,0,22,0.52,1.2,0,0,0,0,0,0,0,0,0,0,111,37,23,122,0,96,29,115,388,89,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 9 | 5/19/2009,2959,0,0,79,1.49,4.4,0,0,0,0,0,0,0,0,0,5,50,137,223,193,35,759,463,64,425,304,31,59,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 10 | 5/20/2009,271,0,0,6,0.13,0.3,0,0,0,0,0,0,0,0,0,47,190,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 11 | ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 12 | ,0CC4,0B52,0014,007C,00A5,,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0051,0000,06D3,052A,0014,005A,0000,0000,0000,0008,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0686,04CC,0000,0000,0000,0000,0000,0000,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 13 | ,1483,0D62,0018,00BA,0109,,0000,0000,0000,0000,0000,0000,0000,0100,007E,005E,0111,01D9,0152,0021,0000,0000,000E,005A,0DBB,0027,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0D62,0000,0000,0000,0000,0000,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 14 | ,209C,13A3,002A,0134,01A5,,0000,0000,0000,0000,0000,0000,0000,008E,1807,02D7,02D6,0007,0000,0000,0000,0079,0028,00EC,002A,009C,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,11AA,01F9,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 15 | ,0B56,0000,0000,0060,0092,,0000,0000,0000,0000,0000,0000,0000,0000,0000,00B6,0541,0069,022F,0246,0000,0000,0000,004F,0032,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 16 | ,0412,0000,0000,0016,0034,,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,006F,0025,0017,007A,0000,0060,001D,0073,0184,0059,0020,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 17 | ,0B8F,0000,0000,004F,0095,,0000,0000,0000,0000,0000,0000,0000,0000,0000,0005,0032,0089,00DF,00C1,0023,02F7,01CF,0040,01A9,0130,001F,003B,00D3,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 18 | ,010F,0000,0000,0006,000D,,0000,0000,0000,0000,0000,0000,0000,0000,0000,002F,00BE,0022,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 19 | -------------------------------------------------------------------------------- /doc/logs/hj720it/pedometerData2.csv: -------------------------------------------------------------------------------- 1 | Kato,, 2 | 3 | Date,Total Steps,Aerobic Steps,Aerobic Walking Time,Calories,Distance,Fat Burned,Steps 12AM,Steps 1AM,Steps 2AM,Steps 3AM,Steps 4AM,Steps 5AM,Steps 6AM,Steps 7AM,Steps 8AM,Steps 9AM,Steps 10AM,Steps 11AM,Steps 12PM,Steps 1PM,Steps 2PM,Steps 3PM,Steps 4PM,Steps 5PM,Steps 6PM,Steps 7PM,Steps 8PM,Steps 9PM,Steps 10PM,Steps 11PM,Aerobic Steps 12AM,Aerobic Steps 1AM,Aerobic Steps 2AM,Aerobic Steps 3AM,Aerobic Steps 4AM,Aerobic Steps 5AM,Aerobic Steps 6AM,Aerobic Steps 7AM,Aerobic Steps 8AM,Aerobic Steps 9AM,Aerobic Steps 10AM,Aerobic Steps 11AM,Aerobic Steps 12PM,Aerobic Steps 1PM,Aerobic Steps 2PM,Aerobic Steps 3PM,Aerobic Steps 4PM,Aerobic Steps 5PM,Aerobic Steps 6PM,Aerobic Steps 7PM,Aerobic Steps 8PM,Aerobic Steps 9PM,Aerobic Steps 10PM,Aerobic Steps 11PM,Used 12AM,Used 1AM,Used 2AM,Used 3AM,Used 4AM,Used 5AM,Used 6AM,Used 7AM,Used 8AM,Used 9AM,Used 10AM,Used 11AM,Used 12PM,Used 1PM,Used 2PM,Used 3PM,Used 4PM,Used 5PM,Used 6PM,Used 7PM,Used 8PM,Used 9PM,Used 10PM,Used 11PM,Event 12AM,Event 1AM,Event 2AM,Event 3AM,Event 4AM,Event 5AM,Event 6AM,Event 7AM,Event 8AM,Event 9AM,Event 10AM,Event 11AM,Event 12PM,Event 1PM,Event 2PM,Event 3PM,Event 4PM,Event 5PM,Event 6PM,Event 7PM,Event 8PM,Event 9PM,Event 10PM,Event 11PM 4 | 5/14/2009,3268,2898,20,124,1.65,7.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,81,0,1747,1322,20,90,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1670,1228,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 5 | 5/15/2009,5251,3426,24,186,2.65,11.1,0,0,0,0,0,0,0,256,126,94,273,473,338,33,0,0,14,90,3515,39,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3426,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 6 | 5/16/2009,8348,5027,42,308,4.21,18.4,0,0,0,0,0,0,0,142,6151,727,726,7,0,0,0,121,40,236,42,156,0,0,0,0,0,0,0,0,0,0,0,0,4522,505,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 7 | 5/17/2009,2902,0,0,96,1.46,5.2,0,0,0,0,0,0,0,0,0,182,1345,105,559,582,0,0,0,79,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 8 | 5/18/2009,1042,0,0,22,0.52,1.2,0,0,0,0,0,0,0,0,0,0,111,37,23,122,0,96,29,115,388,89,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 9 | 5/19/2009,2959,0,0,79,1.49,4.4,0,0,0,0,0,0,0,0,0,5,50,137,223,193,35,759,463,64,425,304,31,59,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 10 | 5/20/2009,959,0,0,19,0.48,1.0,0,0,0,0,0,0,0,0,0,47,190,34,17,133,14,0,64,113,0,99,138,0,99,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0 11 | 5/21/2009,34,0,0,0,0.01,0.0,27,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 12 | -------------------------------------------------------------------------------- /doc/logs/hj720it/pedometerData3.csv: -------------------------------------------------------------------------------- 1 | Kato,, 2 | 3 | Date,Total Steps,Aerobic Steps,Aerobic Walking Time,Calories,Distance,Fat Burned,Steps 12AM,Steps 1AM,Steps 2AM,Steps 3AM,Steps 4AM,Steps 5AM,Steps 6AM,Steps 7AM,Steps 8AM,Steps 9AM,Steps 10AM,Steps 11AM,Steps 12PM,Steps 1PM,Steps 2PM,Steps 3PM,Steps 4PM,Steps 5PM,Steps 6PM,Steps 7PM,Steps 8PM,Steps 9PM,Steps 10PM,Steps 11PM,Aerobic Steps 12AM,Aerobic Steps 1AM,Aerobic Steps 2AM,Aerobic Steps 3AM,Aerobic Steps 4AM,Aerobic Steps 5AM,Aerobic Steps 6AM,Aerobic Steps 7AM,Aerobic Steps 8AM,Aerobic Steps 9AM,Aerobic Steps 10AM,Aerobic Steps 11AM,Aerobic Steps 12PM,Aerobic Steps 1PM,Aerobic Steps 2PM,Aerobic Steps 3PM,Aerobic Steps 4PM,Aerobic Steps 5PM,Aerobic Steps 6PM,Aerobic Steps 7PM,Aerobic Steps 8PM,Aerobic Steps 9PM,Aerobic Steps 10PM,Aerobic Steps 11PM,Used 12AM,Used 1AM,Used 2AM,Used 3AM,Used 4AM,Used 5AM,Used 6AM,Used 7AM,Used 8AM,Used 9AM,Used 10AM,Used 11AM,Used 12PM,Used 1PM,Used 2PM,Used 3PM,Used 4PM,Used 5PM,Used 6PM,Used 7PM,Used 8PM,Used 9PM,Used 10PM,Used 11PM,Event 12AM,Event 1AM,Event 2AM,Event 3AM,Event 4AM,Event 5AM,Event 6AM,Event 7AM,Event 8AM,Event 9AM,Event 10AM,Event 11AM,Event 12PM,Event 1PM,Event 2PM,Event 3PM,Event 4PM,Event 5PM,Event 6PM,Event 7PM,Event 8PM,Event 9PM,Event 10PM,Event 11PM 4 | 5/14/2009,3268,2898,20,124,1.65,7.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,81,0,1747,1322,20,90,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1670,1228,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 5 | 5/15/2009,5251,3426,24,186,2.65,11.1,0,0,0,0,0,0,0,256,126,94,273,473,338,33,0,0,14,90,3515,39,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3426,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 6 | 5/16/2009,8348,5027,42,308,4.21,18.4,0,0,0,0,0,0,0,142,6151,727,726,7,0,0,0,121,40,236,42,156,0,0,0,0,0,0,0,0,0,0,0,0,4522,505,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 7 | 5/17/2009,2902,0,0,96,1.46,5.2,0,0,0,0,0,0,0,0,0,182,1345,105,559,582,0,0,0,79,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 8 | 5/18/2009,1042,0,0,22,0.52,1.2,0,0,0,0,0,0,0,0,0,0,111,37,23,122,0,96,29,115,388,89,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 9 | 5/19/2009,2959,0,0,79,1.49,4.4,0,0,0,0,0,0,0,0,0,5,50,137,223,193,35,759,463,64,425,304,31,59,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 10 | 5/20/2009,959,0,0,19,0.48,1.0,0,0,0,0,0,0,0,0,0,47,190,34,17,133,14,0,64,113,0,99,138,0,99,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0 11 | 5/21/2009,141,0,0,0,0.07,0.0,27,0,0,0,0,0,0,0,0,63,51,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 12 | -------------------------------------------------------------------------------- /doc/logs/hj720it/pedometerSniff1.usblog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qdot/libomron/2687b382eac0faaa7de0f2727fc77c22514f053c/doc/logs/hj720it/pedometerSniff1.usblog -------------------------------------------------------------------------------- /doc/logs/hj720it/pedometerSniff2.usblog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qdot/libomron/2687b382eac0faaa7de0f2727fc77c22514f053c/doc/logs/hj720it/pedometerSniff2.usblog -------------------------------------------------------------------------------- /doc/logs/hj720it/pedometerSniff3.usblog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qdot/libomron/2687b382eac0faaa7de0f2727fc77c22514f053c/doc/logs/hj720it/pedometerSniff3.usblog -------------------------------------------------------------------------------- /doc/omron_protocol_notes.asciidoc: -------------------------------------------------------------------------------- 1 | Omron 790IT Protocol Documentation 2 | ================================== 3 | Kyle Machulis 4 | v1.1, July 4 2009 5 | 6 | == Introduction == 7 | 8 | This document outlines the USB HID based protocol for the Omron 790IT 9 | Blood Pressure Monitor. The protocol allows a user to download 10 | information that was stored on the unit over multiple usages. 11 | 12 | Thanks to Adam Richter for editing and additions to the document. 13 | 14 | == Document Notation == 15 | 16 | The following notation is used in the packet formats in this document 17 | 18 | 0xXX:: refers to a byte that is ignored and can take any value 19 | 0x??:: refers to a byte that is significant but variable 20 | 21 | == Protocol Information == 22 | 23 | === Packet Format === 24 | 25 | The protocol itself does not follow the normal USB HID specification, 26 | instead catching and using the raw reports with its own format. It 27 | does this in order to bypass driver installation on Windows based 28 | machines. 29 | 30 | All output reports are 8 bytes with no HID report ID, but some operating 31 | sytem software (at least under Microsoft Windows) will provide prepend 32 | a byte that is always 0, to indicate report ID 0, so the report will be 33 | appear to be 9 bytes (1 report ID, always 0, 8 data). This is probably 34 | intended to simplify HID report processing by allowing client software 35 | to be written as if all HID devices prepend a one byte report ID. 36 | 37 | In input and output reports, the first data byte specifies the number 38 | of "valid" bytes in the packet. Count starts after the count byte, all 39 | bytes after the count are ignored. 40 | 41 | i.e. In the packet 42 | --------------------------------------- 43 | 0x05 0x01 0x02 0x03 0x04 0x05 0x06 0x07 44 | --------------------------------------- 45 | 46 | Only bytes 1-5 are used, and would look like this in our notation 47 | --------------------------------------- 48 | 0x05 0x01 0x02 0x03 0x04 0x05 0xXX 0xXX 49 | --------------------------------------- 50 | 51 | 0x06 0x07 are ignored and can be anything. 52 | 53 | === Command Format === 54 | 55 | All commands from the computer to the Omron device consit of at least 56 | five bytes. All commands begin with three mnemonic ASCII characters 57 | (except for the "clearing block" command described below, where these 58 | bytes are all zero) followed by one or more data bytes (which may or 59 | may not human readable ASCII, depending on command), followed, by a 60 | terminating checksum byte which is the XOR of the data bytes. 61 | Commands may span multiple output reports. 62 | 63 | === Response Format === 64 | 65 | For returns, the first 2-3 bytes specify the status. Returns may be 66 | broken up over multiple input reports 67 | 68 | Successful input reports begin with ASCII "OK" and are either exactly two 69 | bytes or at least five bytes, the last of which is a checksum of the 70 | bytes after the "OK". 71 | -------------- 72 | 0x4F 0x4B [ 0x00 ... CHECKSUM ] 73 | (ASCII: "OK") 74 | (The CHECKSUM byte is the XOR of bytes designateed by "...") 75 | -------------- 76 | 77 | An exception to the statement about checksums above is the response to 78 | the "END" command which is "OFF\r\n" with no checksum byte. Also a 79 | response of zero bytes to an "END" command may have been observed 80 | under Linux, but this may have been a figment of a user level bug. 81 | 82 | 83 | 84 | Unsuccessful input reports will have their first two bytes as 0x4E 0x4F. 85 | ------------- 86 | 0x4E 0x4F 87 | (ASCII: "NO") 88 | ------------- 89 | 90 | Initialization 91 | -------------- 92 | 93 | The Omron 790IT has 3 data retrieval modes that need to be set before 94 | data can be pulled from the unit. 95 | 96 | These data modes are set by way of HID Feature Requests. All feature 97 | requests are 3 bytes (1 report ID, always 0, and 2 data bytes). 98 | 99 | .Device Information 100 | --------- 101 | 0x01 0x01 102 | --------- 103 | 104 | .Individual Reading Information 105 | --------- 106 | 0x74 0xbc 107 | --------- 108 | 109 | .Weekly Average Information 110 | --------- 111 | 0x10 0x74 112 | --------- 113 | 114 | After a mode is set, a 'clearing block' is sent. These consist of: 115 | 116 | - 7 bytes out, all 0 117 | - 7 bytes in, all 0 118 | - 3 packets of 7 bytes out, all 0 119 | - 1 packet of 2 bytes out, all 0 120 | - One packet in of success status message, otherwise repeat above two steps 121 | 122 | == Device Information Mode Commands == 123 | 124 | === Get Unit Version === 125 | 126 | ==== Description ==== 127 | Used to retrieve the version of the unit, in ASCII string format 128 | 129 | ==== Command ==== 130 | ------------------------ 131 | 0x56 0x45 0x52 0x30 0x30 132 | (ASCII: "VER00") 133 | (Three byte ASCII command "VER", argument "0", checksum checksum "0") 134 | ------------------------ 135 | 136 | ==== Parameters ==== 137 | None 138 | 139 | ==== Return Format ==== 140 | 15 bytes (3 bytes for "OK" success string, 12 byte ASCII string, not 141 | null terminated, giving the unit version) 142 | 143 | ==== Output Report Example ==== 144 | ------------------------ 145 | 0x56 0x45 0x52 0x30 0x30 146 | (Three byte ASCII command "VER", argument byte ASCII "0", checksum byte ASCII "0") 147 | ------------------------ 148 | 149 | ==== Output Report Example in HID Raw Report Format ==== 150 | --------------------------------------- 151 | 0x05 0x56 0x45 0x52 0x30 0x30 0xXX 0xXX 152 | (Byte count 5, command "VER", argument "0", argument checksum "0") 153 | --------------------------------------- 154 | 155 | ==== Return Example ==== 156 | ----------------------------------------------------------- 157 | 0x4d 0x37 0x30 0x38 0x30 0x49 0x54 0x20 0x32 0x30 0x37 0x4a 158 | (ASCII: "M7080IT 207J") 159 | (data bytes: ASCII "M7080IT 207", data checksum: 0x4a ) 160 | ----------------------------------------------------------- 161 | 162 | ==== Return Example in HID Raw Report Format ==== 163 | --------------------------------------- 164 | 0x07 0x4f 0x4b 0x00 0x4d 0x37 0x30 0x38 165 | 0x07 0x30 0x49 0x54 0x20 0x32 0x30 0x37 166 | 0x01 0x4a 0xXX 0xXX 0xXX 0xXX 0xXX 0xXX 167 | --------------------------------------- 168 | 169 | === Get Unit PRF === 170 | 171 | ==== Description ==== 172 | Used to retrieve whatever the 'PRF' is for the unit. ASCII string, 173 | could be some sort of odd bitfield? 174 | 175 | ==== Command ==== 176 | ------------------------ 177 | 0x50 0x52 0x46 0x30 0x30 178 | (ASCII: "PRF00") 179 | ------------------------ 180 | 181 | ==== Parameters ==== 182 | None 183 | 184 | ==== Return Format ==== 185 | 14 bytes (3 bytes for "OK" success string, 11 byte ASCII string) 186 | 187 | ==== Output Report Example ==== 188 | ------------------------ 189 | 0x50 0x52 0x46 0x30 0x30 190 | ------------------------ 191 | 192 | ==== Output Report Example in HID Raw Report Format ==== 193 | --------------------------------------- 194 | 0x05 0x50 0x52 0x46 0x30 0x30 0xXX 0xXX 195 | (Byte count 5, ASCII "PRF", data byte "0", data checksum "0") 196 | --------------------------------------- 197 | 198 | ==== Return Example ==== 199 | ------------------------------------------------------ 200 | 0x30 0x30 0x31 0x30 0x31 0x30 0x30 0x30 0x30 0x30 0x00 201 | (ASCII: '001010000') 202 | (ASCII data '0010100', data checksum: 0) 203 | ------------------------------------------------------ 204 | 205 | ==== Return Example in HID Raw Report Format ==== 206 | --------------------------------------- 207 | 0x07 0x4f 0x4b 0x00 0x30 0x30 0x31 0x30 208 | 0x07 0x31 0x30 0x30 0x30 0x30 0x30 0x00 209 | --------------------------------------- 210 | 211 | === Get Unit SRL === 212 | 213 | ==== Description ==== 214 | Used to retrieve whatever the 'SRL' is for the unit. ASCII string, 215 | could be serial number? 216 | 217 | ==== Command ==== 218 | ------------------------ 219 | 0x53 0x52 0x4c 0x30 0x30 220 | (ASCII: "SRL00") 221 | ------------------------ 222 | 223 | ==== Parameters ==== 224 | None 225 | 226 | ==== Return Format ==== 227 | 11 bytes (3 bytes for "OK" success string, 8 bytes, binary, not 228 | sure of context) 229 | 230 | ==== Output Report Example ==== 231 | ------------------------ 232 | 0x53 0x52 0x4c 0x30 0x30 233 | ------------------------ 234 | 235 | ==== Output Report Example in HID Raw Report Format ==== 236 | --------------------------------------- 237 | 0x05 0x53 0x52 0x4c 0x30 0x30 0xXX 0xXX 238 | --------------------------------------- 239 | 240 | ==== Return Example ==== 241 | --------------------------------------- 242 | 0x06 0x00 0x00 0x00 0x00 0x00 0x00 0x06 243 | --------------------------------------- 244 | 245 | ==== Return Example in HID Raw Report Format ==== 246 | --------------------------------------- 247 | 0x07 0x4f 0x4b 0x00 0x06 0x00 0x00 0x00 248 | 0x04 0x00 0x00 0x00 0x06 0xXX 0xXX 0xXX 249 | --------------------------------------- 250 | 251 | == Individual Reading Mode Commands == 252 | 253 | === Get Individual Reading Count === 254 | 255 | ==== Description ==== 256 | Used to retreive how many sessions are currently stored on the machine 257 | 258 | ==== Command ==== 259 | --------------------------------------- 260 | 0x47 0x44 0x43 0x00 bank 0x00 0x00 checksum 261 | ASCII: "GDC" (Get Data Count?) 262 | index = 0..(value returned by GDC - 1) 263 | bank = 0x00, 0x01 or 0x02, perhaps for user A, user B, combined? 264 | checksum = the XOR of the bytes after "GDC" 265 | --------------------------------------- 266 | 267 | ==== Parameters ==== 268 | Which bank to query, last byte of command (NEED TO CONFIRM) 269 | 270 | ==== Return Format ==== 271 | 8 bytes (3 bytes for "OK" success string, 5 bytes, binary, not sure of context) 272 | 273 | Byte 3: Number of available sessions 274 | 275 | ==== Output Report Example ==== 276 | --------------------------------------- 277 | 0x47 0x44 0x43 0x00 0x00 0x00 0x00 0x01 278 | --------------------------------------- 279 | 280 | ==== Output Report Example in HID Raw Report Format ==== 281 | --------------------------------------- 282 | 0x07 0x47 0x44 0x43 0x00 0x00 0x00 0x00 283 | 0x01 0x01 0xXX 0xXX 0xXX 0xXX 0xXX 0xXX 284 | --------------------------------------- 285 | 286 | ==== Return Example ==== 287 | ------------------------ 288 | 0x00 0x0a 0x00 0x08 0x02 289 | ------------------------ 290 | 291 | ==== Return Example in HID Raw Report Format ==== 292 | --------------------------------------- 293 | 0x07 0x4f 0x4b 0x00 0x00 0x0a 0x00 0x08 294 | 0x01 0x02 0xXX 0xXX 0xXX 0xXX 0xXX 0xXX 295 | --------------------------------------- 296 | 297 | === Get Individual Reading === 298 | 299 | ==== Description ==== 300 | Retrieve information about a single reading 301 | 302 | ==== Command ==== 303 | --------------------------------------- 304 | 0x47 0x4d 0x45 0x00 bank 0x00 index checksum 305 | ASCII: "GME" (Get Measurement?) 306 | index = 0..(value returned by GDC - 1) 307 | bank = 0x00, 0x01 or 0x02, perhaps for user A, user B, combined? 308 | checksum = the XOR of the bytes after "GME" 309 | --------------------------------------- 310 | 311 | ==== Parameters ==== 312 | Index of record, last 2 bytes of command 313 | 314 | ==== Return Format ==== 315 | 17 bytes (3 bytes for "OK" success string, 14 bytes, binary) 316 | Will sometimes return "NO" message. If this happens, requery using the same command 317 | 318 | Byte 0:: Last 2 digits of year 319 | Byte 1:: Month 320 | Byte 2:: Day 321 | Byte 3:: Hour (24-hour format) (NEED TO CONFIRM) 322 | Byte 4:: Minute 323 | Byte 5:: Seconds 324 | Byte 6:: UNKNOWN 325 | Byte 7:: UNKNOWN 326 | Byte 8:: SYS 327 | Byte 9:: DIA 328 | Byte A:: Pulse 329 | Byte B:: UNKNOWN 330 | Byte C:: Status Flags 331 | - 0x0X - Standalone reading 332 | - 0x1X - First reading of a 3 reading average (TruRead function) 333 | - 0x2X - Second reading of a 3 reading average (TruRead function) 334 | - 0x3X - Third reading of a 3 reading average (TruRead function) 335 | - Others: UNKNOWN 336 | Byte D:: Checksum (XOR of bytes 0..C) 337 | 338 | ==== Output Report Example ==== 339 | Command gets newest available record 340 | --------------------------------------- 341 | 0x47 0x4d 0x45 0x00 0x00 0x00 0x00 0x00 342 | --------------------------------------- 343 | 344 | ==== Output Report Example in HID Raw Report Format ==== 345 | --------------------------------------- 346 | 0x07 0x47 0x4d 0x45 0x00 0x00 0x00 0x00 347 | 0x01 0x00 0xXX 0xXX 0xXX 0xXX 0xXX 0xXX 348 | --------------------------------------- 349 | 350 | ==== Return Example ==== 351 | --------------------------------------------------------------------- 352 | 0x07 0x01 0x03 0x00 0x06 0x33 0x00 0x00 0x70 0x4b 0x47 0x00 0x00 0x4c 353 | --------------------------------------------------------------------- 354 | 355 | Year:: 07 356 | Month:: 01 357 | Day:: 03 358 | Hour:: 00 359 | Minute:: 06 360 | Seconds:: 33 361 | SYS:: 0x70 (112) 362 | DIA:: 0x4b (75) 363 | Pulse:: 0x47 (71) 364 | Read Type:: Standalone 365 | 366 | ==== Return Example in HID Raw Report Format ==== 367 | --------------------------------------- 368 | 0x07 0x4f 0x4b 0x00 0x07 0x01 0x03 0x00 369 | 0x07 0x06 0x33 0x00 0x00 0x70 0x4b 0x47 370 | 0x03 0x00 0x00 0x4c 0xXX 0xXX 0xXX 0xXX 371 | --------------------------------------- 372 | 373 | == Weekly Average Mode Commands == 374 | 375 | === Get Weekly Morning/Evening Data === 376 | 377 | ==== Description ==== 378 | Retrieve information about a weekly morning/evening average 379 | 380 | ==== Command ==== 381 | -------------------------------------------- 382 | 0x47 0x4d 0x41 0x00 bank index 0x00 0x00 checksum 383 | ASCII: "GMA" (Get Morning Average) 384 | or 385 | 0x47 0x45 0x41 0x00 bank index 0x00 0x00 checksum 386 | ASCII: "GEA" (Get Evening Average) 387 | 388 | index = 0..7? 389 | bank = 0x00, 0x01 or 0x02, perhaps for user A, user B, combined? 390 | checksum = the XOR of the bytes after "GMA" or "GEA" 391 | -------------------------------------------- 392 | 393 | ==== Parameters ==== 394 | Index of record 395 | 396 | ==== Return Format ==== 397 | 12 bytes (3 bytes for "OK" success string, 9 bytes, binary) 398 | 399 | Byte 0:: UNKNOWN (always 0x80?) 400 | Byte 1:: UNKNOWN (always 0..7?) 401 | Byte 2:: Last two digits of year 402 | Byte 3:: Month 403 | Byte 4:: Day 404 | Byte 5:: SYS minus 25 (NEED TO CONFIRM) (0 = no readings this week?) 405 | Byte 6:: DIA (0 = no readings this week?) 406 | Byte 7:: Pulse 407 | Byte 8:: Checksum (XOR of bytes 0..7) 408 | 409 | ==== Output Report Example ==== 410 | Command gets 7th record 411 | -------------------------------------------- 412 | 0x47 0x4d 0x41 0x00 0x00 0x06 0x00 0x00 0x06 413 | -------------------------------------------- 414 | 415 | ==== Output Report Example in HID Raw Report Format ==== 416 | --------------------------------------- 417 | 0x07 0x47 0x4d 0x41 0x00 0x00 0x00 0x06 418 | 0x02 0x00 0x06 0x00 0x00 0x00 0x00 0x00 419 | --------------------------------------- 420 | 421 | ==== Return Example ==== 422 | -------------------------------------------- 423 | 0x80 0x01 0x09 0x04 0x13 0x71 0x69 0x70 0xf7 424 | -------------------------------------------- 425 | 426 | SYS:: 138 (0x71 + 0x19, unit says 138 though. This lines up across other readings too) 427 | DIA:: 105 (0x69) 428 | Pulse:: 112 (0x70) 429 | 430 | ==== Return Example in HID Raw Report Format ==== 431 | --------------------------------------- 432 | 0x07 0x4f 0x4b 0x00 0x80 0x01 0x09 0x04 433 | 0x05 0x13 0x71 0x69 0x70 0xf7 0xXX 0xXX 434 | --------------------------------------- 435 | 436 | == Utility Commands == 437 | 438 | === End Data Request === 439 | 440 | ==== Description ==== 441 | Notifies the unit that the transfer session is over. Device will turn 442 | off after this command is sent. 443 | 444 | ==== Command ==== 445 | ------------------------ 446 | 0x45 0x4E 0x44 0xFF 0xFF 447 | (ASCII: "END") 448 | ------------------------ 449 | 450 | ==== Parameters ==== 451 | None 452 | 453 | ==== Return Format ==== 454 | 5 Bytes (ASCII "OFF\r\n"), signaling that the unit is turning off 455 | 456 | ==== Output Report Example ==== 457 | ------------------------ 458 | 0x45 0x4E 0x44 0xFF 0xFF 459 | ------------------------ 460 | 461 | ==== Output Report Example in HID Raw Report Format ==== 462 | --------------------------------------- 463 | 0x05 0x45 0x4E 0x44 0xFF 0xFF 0xXX 0xXX 464 | --------------------------------------- 465 | 466 | ==== Return Example ==== 467 | ------------------------ 468 | 0x4F 0x46 0x46 0x0D 0x0A 469 | (ASCII: "OFF\r\n") 470 | ------------------------ 471 | 472 | ==== Return Example in HID Raw Report Format ==== 473 | --------------------------------------- 474 | 0x07 0x4F 0x46 0x46 0x0D 0x0A 0xXX 0xXX 475 | --------------------------------------- 476 | 477 | == Further Information == 478 | 479 | For further information, visit: 480 | 481 | - http://www.github.com/qdot/libomron/[libomron github site] 482 | - http://www.nonpolynomial.com/[Nonpolynomial Labs] 483 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ###################################################################################### 2 | # Build function for omron_790IT_test 3 | ###################################################################################### 4 | 5 | SET(LIBOMRON_EXAMPLE_LIBS ${libomron_LIBRARY} ${LIBOMRON_REQUIRED_LIBS}) 6 | 7 | #linux needs math lib 8 | IF(UNIX AND NOT APPLE) 9 | LIST(APPEND LIBOMRON_EXAMPLE_LIBS m) 10 | ENDIF() 11 | 12 | SET(EXAMPLES omron_720IT_test omron_790IT_test) 13 | 14 | FOREACH(EX ${EXAMPLES}) 15 | SET(SRCS ${EX}/${EX}.c) 16 | 17 | BUILDSYS_BUILD_EXE( 18 | NAME ${EX} 19 | SOURCES "${SRCS}" 20 | CXX_FLAGS FALSE 21 | LINK_LIBS "${LIBOMRON_EXAMPLE_LIBS}" 22 | LINK_FLAGS FALSE 23 | DEPENDS omron_DEPEND 24 | SHOULD_INSTALL TRUE 25 | ) 26 | ENDFOREACH() 27 | 28 | SET(SRCS omron_720IT_test/omron_720IT_csv_dump.c) 29 | BUILDSYS_BUILD_EXE( 30 | NAME omron_720IT_csv_dump 31 | SOURCES "${SRCS}" 32 | CXX_FLAGS FALSE 33 | LINK_LIBS "${LIBOMRON_EXAMPLE_LIBS}" 34 | LINK_FLAGS FALSE 35 | DEPENDS omron_DEPEND 36 | SHOULD_INSTALL TRUE 37 | ) 38 | -------------------------------------------------------------------------------- /examples/omron_720IT_test/omron_720IT_csv_dump.c: -------------------------------------------------------------------------------- 1 | #include "libomron/omron.h" 2 | #include 3 | #include /* atoi */ 4 | #include 5 | #include /* getopt */ 6 | 7 | #define SECONDS_PER_DAY 86400 8 | 9 | int main(int argc, char** argv) 10 | { 11 | omron_device* test = omron_create(); 12 | int ret; 13 | int i; 14 | int day; 15 | int data_count; 16 | unsigned char str[30]; 17 | unsigned char data[37]; 18 | int bank = 0; 19 | omron_pd_profile_info p; 20 | omron_pd_count_info c; 21 | char time_str[20]; 22 | struct tm *timeptr; 23 | time_t today_secs, other_secs; 24 | int ch, clear_flag = 0; 25 | 26 | while((ch = getopt(argc, argv, "d")) != -1) { 27 | switch (ch) { 28 | case 'd': 29 | clear_flag = 1; 30 | break; 31 | } 32 | } 33 | 34 | if(test == NULL) 35 | { 36 | printf("Cannot initialize USB core!\n"); 37 | return 1; 38 | } 39 | 40 | ret = omron_get_count(test, OMRON_VID, OMRON_PID); 41 | 42 | if(!ret) 43 | { 44 | printf("No omron 720ITs connected!\n"); 45 | return 1; 46 | } 47 | //printf("Found %d omron 720ITs\n", ret); 48 | 49 | ret = omron_open(test, OMRON_VID, OMRON_PID, 0); 50 | if(ret < 0) 51 | { 52 | printf("Cannot open omron 720IT!\n"); 53 | return 1; 54 | } 55 | //printf("Opened omron 720IT\n"); 56 | 57 | 58 | ret = omron_get_device_version(test, str); 59 | if(ret < 0) 60 | { 61 | printf("Cannot get device version!\n"); 62 | } 63 | else 64 | { 65 | //printf("Device serial: %s\n", str); 66 | } 67 | 68 | 69 | c = omron_get_pd_data_count(test); 70 | 71 | printf("Daily Reading Blocks: %d\n", c.daily_count); 72 | printf("Hourly Reading Blocks: %d\n", c.hourly_count); 73 | 74 | data_count = c.daily_count < c.hourly_count ? c.daily_count : c.hourly_count; 75 | 76 | if(data_count > 0) { 77 | printf("Date,Total Steps,Aerobic Steps,Aerobic Walking Time,Calories,Distance,Fat Burned,Steps 12AM,Steps 1AM,Steps 2AM,Steps 3AM,Steps 4AM,Steps 5AM,Steps 6AM,Steps 7AM,Steps 8AM,Steps 9AM,Steps 10AM,Steps 11AM,Steps 12PM,Steps 1PM,Steps 2PM,Steps 3PM,Steps 4PM,Steps 5PM,Steps 6PM,Steps 7PM,Steps 8PM,Steps 9PM,Steps 10PM,Steps 11PM,Aerobic Steps 12AM,Aerobic Steps 1AM,Aerobic Steps 2AM,Aerobic Steps 3AM,Aerobic Steps 4AM,Aerobic Steps 5AM,Aerobic Steps 6AM,Aerobic Steps 7AM,Aerobic Steps 8AM,Aerobic Steps 9AM,Aerobic Steps 10AM,Aerobic Steps 11AM,Aerobic Steps 12PM,Aerobic Steps 1PM,Aerobic Steps 2PM,Aerobic Steps 3PM,Aerobic Steps 4PM,Aerobic Steps 5PM,Aerobic Steps 6PM,Aerobic Steps 7PM,Aerobic Steps 8PM,Aerobic Steps 9PM,Aerobic Steps 10PM,Aerobic Steps 11PM,Used 12AM,Used 1AM,Used 2AM,Used 3AM,Used 4AM,Used 5AM,Used 6AM,Used 7AM,Used 8AM,Used 9AM,Used 10AM,Used 11AM,Used 12PM,Used 1PM,Used 2PM,Used 3PM,Used 4PM,Used 5PM,Used 6PM,Used 7PM,Used 8PM,Used 9PM,Used 10PM,Used 11PM,Event 12AM,Event 1AM,Event 2AM,Event 3AM,Event 4AM,Event 5AM,Event 6AM,Event 7AM,Event 8AM,Event 9AM,Event 10AM,Event 11AM,Event 12PM,Event 1PM,Event 2PM,Event 3PM,Event 4PM,Event 5PM,Event 6PM,Event 7PM,Event 8PM,Event 9PM,Event 10PM,Event 11PM\n"); 78 | today_secs = time(NULL); 79 | for(i = 0; i < data_count; ++i) { 80 | other_secs = (time_t)(today_secs - i * SECONDS_PER_DAY); 81 | timeptr = localtime(&other_secs); 82 | strftime(time_str, 20, "%m/%d/%Y", timeptr); 83 | 84 | omron_pd_daily_data d = omron_get_pd_daily_data(test, i); 85 | printf("%s,%d,%d,%d,%d,%0.2f,%0.1f", time_str, d.total_steps, d.total_aerobic_steps, d.total_aerobic_walking_time, d.total_calories, d.total_distance, d.total_fat_burn); 86 | 87 | omron_pd_hourly_data* h = omron_get_pd_hourly_data(test, i); 88 | // hour loops 89 | int j; 90 | for(j = 0; j < 24; ++j) 91 | { 92 | printf(",%d", h[j].regular_steps); 93 | //printf("d: %d Hour: %d - On: %d - Steps: %d roby: %d Event: %d \n", h[j].day_serial, h[j].hour_serial, h[j].is_attached > 0, h[j].regular_steps, h[j].aerobic_steps, h[j].event); 94 | } 95 | for(j = 0; j < 24; ++j) 96 | { 97 | printf(",%d", h[j].aerobic_steps); 98 | } 99 | for(j = 0; j < 24; ++j) 100 | { 101 | printf(",%d", h[j].is_attached); 102 | } 103 | for(j = 0; j < 24; ++j) 104 | { 105 | printf(",%d", h[j].event); 106 | } 107 | printf("\n"); 108 | 109 | free(h); 110 | } 111 | } 112 | if(clear_flag) { 113 | ret = omron_clear_pd_memory(test); 114 | } 115 | ret = omron_close(test); 116 | if(ret < 0) 117 | { 118 | printf("Cannot close omron 720IT!\n"); 119 | return 1; 120 | } 121 | 122 | omron_delete(test); 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /examples/omron_720IT_test/omron_720IT_test.c: -------------------------------------------------------------------------------- 1 | #include "libomron/omron.h" 2 | #include 3 | #include /* atoi */ 4 | 5 | int main(int argc, char** argv) 6 | { 7 | omron_device* test = omron_create(); 8 | int ret; 9 | int i; 10 | int data_count; 11 | unsigned char str[30]; 12 | int bank = 0; 13 | omron_pd_profile_info p; 14 | omron_pd_count_info c; 15 | 16 | if (argc > 1) 17 | bank = atoi(argv[1]); 18 | 19 | if(test == NULL) 20 | { 21 | printf("Cannot initialize USB core!\n"); 22 | return 1; 23 | } 24 | 25 | ret = omron_get_count(test, OMRON_VID, OMRON_PID); 26 | 27 | if(!ret) 28 | { 29 | printf("No omron 720ITs connected!\n"); 30 | return 1; 31 | } 32 | printf("Found %d omron 720ITs\n", ret); 33 | 34 | ret = omron_open(test, OMRON_VID, OMRON_PID, 0); 35 | if(ret < 0) 36 | { 37 | printf("Cannot open omron 720IT!\n"); 38 | return 1; 39 | } 40 | printf("Opened omron 720IT\n"); 41 | 42 | ret = omron_get_device_version(test, str); 43 | if(ret < 0) 44 | { 45 | printf("Cannot get device version!\n"); 46 | } 47 | else 48 | { 49 | printf("Device serial: %s\n", str); 50 | } 51 | 52 | p = omron_get_pd_profile(test); 53 | printf("Weight: %d pounds\n", p.weight); 54 | printf("Stride: %d inches\n", p.stride); 55 | c = omron_get_pd_data_count(test); 56 | printf("Daily Reading Blocks: %d\n", c.daily_count); 57 | printf("Hourly Reading Blocks: %d\n", c.hourly_count); 58 | 59 | data_count = c.daily_count > c.hourly_count ? c.daily_count : c.hourly_count; 60 | for(i = 0; i < data_count; ++i) 61 | { 62 | if(i < c.daily_count) { 63 | omron_pd_daily_data d = omron_get_pd_daily_data(test, i); 64 | printf("DRB D: %2d -Steps: %d -aSteps: %d\n", i, d.total_steps, d.total_aerobic_steps); 65 | } 66 | if(i < c.hourly_count) { 67 | omron_pd_hourly_data* h = omron_get_pd_hourly_data(test, i); 68 | int j; 69 | int tots = 0, tota = 0; 70 | for(j = 0; j < 24; ++j) 71 | { 72 | printf("D: %2d -H: %2d -On: %d -Steps: %5d -aSteps: %5d\n", i, j, h[j].is_attached > 0, h[j].regular_steps, h[j].aerobic_steps); 73 | tots += h[j].regular_steps; 74 | tota += h[j].aerobic_steps; 75 | } 76 | printf("HRB D: %2d -Steps: %d -aSteps: %d\n", i, tots, tota); 77 | free(h); 78 | } 79 | } 80 | 81 | ret = omron_close(test); 82 | if(ret < 0) 83 | { 84 | printf("Cannot close omron 720IT!\n"); 85 | return 1; 86 | } 87 | 88 | omron_delete(test); 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /examples/omron_790IT_test/omron_790IT_test.c: -------------------------------------------------------------------------------- 1 | #include "libomron/omron.h" 2 | #include 3 | #include /* atoi */ 4 | 5 | int main(int argc, char** argv) 6 | { 7 | omron_device* test; 8 | int ret; 9 | int i; 10 | int data_count; 11 | unsigned char str[30]; 12 | int bank = 0; 13 | 14 | if (argc > 1) 15 | bank = atoi(argv[1]); 16 | 17 | test = omron_create(); 18 | 19 | ret = omron_get_count(test, OMRON_VID, OMRON_PID); 20 | 21 | if(!ret) 22 | { 23 | printf("No omron 790ITs connected!\n"); 24 | return 1; 25 | } 26 | printf("Found %d omron 790ITs\n", ret); 27 | 28 | ret = omron_open(test, OMRON_VID, OMRON_PID, 0); 29 | if(ret < 0) 30 | { 31 | printf("Cannot open omron 790IT!\n"); 32 | return 1; 33 | } 34 | printf("Opened omron 790IT\n", ret); 35 | 36 | ret = omron_get_device_version(test, str); 37 | if(ret < 0) 38 | { 39 | printf("Cannot get device version!\n"); 40 | } 41 | else 42 | { 43 | printf("Device serial: %s\n", str); 44 | } 45 | 46 | ret = omron_get_bp_profile(test, str); 47 | if(ret < 0) 48 | { 49 | printf("Cannot get device prf!\n"); 50 | } 51 | else 52 | { 53 | printf("Device version: %s\n", str); 54 | } 55 | 56 | data_count = omron_get_daily_data_count(test, bank); 57 | printf("AJR data count: %d\n", data_count); 58 | if(data_count < 0) 59 | { 60 | printf("Cannot get device prf!\n"); 61 | } 62 | 63 | for(i = data_count - 1; i >= 0; --i) 64 | { 65 | omron_bp_day_info r = omron_get_daily_bp_data(test, bank, i); 66 | if(!r.present) 67 | { 68 | i = i + 1; 69 | continue; 70 | } 71 | printf("%.2d/%.2d/20%.2d %.2d:%.2d:%.2d SYS: %3d DIA: %3d PULSE: %3d\n", r.day, r.month, r.year, r.hour, r.minute, r.second, r.sys, r.dia, r.pulse); 72 | } 73 | 74 | printf("Weekly info:\n"); 75 | for(i = 0; i < 9; i++) { 76 | omron_bp_week_info w; 77 | 78 | w = omron_get_weekly_bp_data(test, bank, i, 0); 79 | if (w.present && w.dia != 0) 80 | printf("Morning[%d %02d/%02d/20%02d] = sys:%d dia:%d pulse:%d.\n", i, w.day, w.month, w.year, w.sys, w.dia, w.pulse); 81 | 82 | w = omron_get_weekly_bp_data(test, bank, i, 1); 83 | if (w.present && w.dia != 0) 84 | printf("Evening[%d %02d/%02d/20%02d] = sys:%d dia:%d pulse:%d.\n", i, w.day, w.month, w.year, w.sys, w.dia, w.pulse); 85 | } 86 | 87 | 88 | 89 | ret = omron_close(test); 90 | if(ret < 0) 91 | { 92 | printf("Cannot close omron 790IT!\n"); 93 | return 1; 94 | } 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /include/libomron/omron.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Declaration file for Omron Health User Space Driver 3 | * 4 | * Copyright (c) 2009-2010 Kyle Machulis 5 | * 6 | * More info on Nonpolynomial Labs @ http://www.nonpolynomial.com 7 | * 8 | * Sourceforge project @ http://www.github.com/qdot/libomron/ 9 | * 10 | * This library is covered by the BSD License 11 | * Read LICENSE_BSD.txt for details. 12 | */ 13 | 14 | #ifndef LIBOMRON_H 15 | #define LIBOMRON_H 16 | 17 | /******************************************************************************* 18 | * 19 | * Headers 20 | * 21 | ******************************************************************************/ 22 | 23 | #define E_NPUTIL_DRIVER_ERROR -1 24 | #define E_NPUTIL_NOT_INITED -2 25 | #define E_NPUTIL_NOT_OPENED -3 26 | 27 | #include 28 | 29 | #if defined(WIN32) 30 | #define WIN32_LEAN_AND_MEAN 31 | #include 32 | 33 | #if defined(OMRON_DYNAMIC) 34 | #define OMRON_DECLSPEC __declspec(dllexport) 35 | #else 36 | #define OMRON_DECLSPEC 37 | #endif 38 | 39 | /** 40 | * Structure to hold information about Windows HID devices. 41 | * 42 | * @ingroup CoreFunctions 43 | */ 44 | typedef struct { 45 | /// Windows device handle 46 | HANDLE _dev; 47 | /// 0 if device is closed, > 0 otherwise 48 | int _is_open; 49 | /// 0 if device is initialized, > 0 otherwise 50 | int _is_inited; 51 | } omron_device_impl; 52 | #else 53 | #define OMRON_DECLSPEC 54 | #include "libusb-1.0/libusb.h" 55 | typedef struct { 56 | struct libusb_context* _context; 57 | struct libusb_device_handle* _device; 58 | struct libusb_transfer* _in_transfer; 59 | struct libusb_transfer* _out_transfer; 60 | int _is_open; 61 | int _is_inited; 62 | } omron_device_impl; 63 | #endif 64 | 65 | /******************************************************************************* 66 | * 67 | * Const global values 68 | * 69 | ******************************************************************************/ 70 | 71 | /// Vendor ID for all omron health devices 72 | static const uint32_t OMRON_VID = 0x0590; 73 | /// Product ID for all omron health devices 74 | static const uint32_t OMRON_PID = 0x0028; 75 | 76 | /// Out endpoint for all omron health devices 77 | static const uint32_t OMRON_OUT_ENDPT = 0x02; 78 | /// In endpoint for all omron health devices 79 | static const uint32_t OMRON_IN_ENDPT = 0x81; 80 | 81 | /******************************************************************************* 82 | * 83 | * Omron device enumerations 84 | * 85 | ******************************************************************************/ 86 | 87 | /** 88 | * Enumeration for different omron device modes 89 | * 90 | * These modes dictate what we're currently trying to do with the 91 | * omron device. We send a control message with the mode, then 92 | * do things like get device info (serial number, version, etc...), 93 | * or engage in specific device communication events, like reading 94 | * pedometer or blood pressure data 95 | */ 96 | typedef enum 97 | { 98 | /// Clearing modes and startup/shutdown 99 | NULL_MODE = 0x0000, 100 | /// Getting serial numbers, version, etc... 101 | DEVICE_INFO_MODE = 0x1111, 102 | /// Daily blood pressure info mode 103 | DAILY_INFO_MODE = 0x74bc, 104 | /// Weekly blood pressure info mode 105 | WEEKLY_INFO_MODE = 0x1074, 106 | /// Pedometer info mode 107 | PEDOMETER_MODE = 0x0102 108 | } omron_mode; 109 | 110 | /** 111 | * Enumeration of device state 112 | * 113 | * Keeps the state of the device, and the current mode that it's in. If 114 | * we issue a command that needs a different mode, we can use the state 115 | * stored here to check that. 116 | */ 117 | typedef struct 118 | { 119 | /// Device implementation 120 | omron_device_impl device; 121 | /// Mode the device is currently in 122 | omron_mode device_mode; 123 | } omron_device; 124 | 125 | /** 126 | * Enumeration of device information 127 | * 128 | * Stores information about the device version, serial, etc... 129 | */ 130 | typedef struct 131 | { 132 | /// Version of the device 133 | uint8_t version[13]; 134 | /// Can't remember what this is 135 | uint8_t prf[11]; 136 | /// Serial number of the device 137 | uint8_t srl[8]; 138 | } omron_device_info; 139 | 140 | /******************************************************************************* 141 | * 142 | * Blood pressure monitor specific enumerations 143 | * 144 | ******************************************************************************/ 145 | 146 | /** 147 | * Enumeration for daily blood pressure info 148 | * 149 | * Stores information taken on a daily basis for blood pressure 150 | * Usually, we consider there to be one morning and one evening 151 | * reading. 152 | */ 153 | typedef struct 154 | { 155 | /// Day of reading 156 | uint32_t day; 157 | /// Month of reading 158 | uint32_t month; 159 | /// Year of reading 160 | uint32_t year; 161 | /// Hour of reading 162 | uint32_t hour; 163 | /// Minute of reading 164 | uint32_t minute; 165 | /// Second of reading 166 | uint32_t second; 167 | /// No idea 168 | uint8_t unknown_1[2]; 169 | /// SYS reading 170 | uint32_t sys; 171 | /// DIA reading 172 | uint32_t dia; 173 | /// Pulse reading 174 | uint32_t pulse; 175 | /// No idea 176 | uint8_t unknown_2[3]; 177 | /// 1 if week block is filled, 0 otherwise 178 | uint8_t present; 179 | } omron_bp_day_info; 180 | 181 | /** 182 | * Enumeration for weekly blood pressure info 183 | * 184 | * Stores information averages for a week 185 | */ 186 | typedef struct 187 | { 188 | /// always 0x00 189 | uint8_t unknown_1; 190 | /// always 0x80 191 | uint8_t unknown_2; 192 | /// Year of reading 193 | uint32_t year; 194 | /// Month of reading 195 | uint32_t month; 196 | /// Day that weekly average starts on 197 | uint32_t day; 198 | /// always 0 199 | uint8_t unknown_3; 200 | /// SYS average for week 201 | int32_t sys; 202 | /// DIA average for week 203 | int32_t dia; 204 | /// Pulse average for week 205 | int32_t pulse; 206 | /// 1 if week block is filled, 0 otherwise 207 | uint8_t present; 208 | } omron_bp_week_info; 209 | 210 | 211 | /******************************************************************************* 212 | * 213 | * Pedometer specific enumerations 214 | * 215 | ******************************************************************************/ 216 | 217 | /** 218 | * Enumeration for pedometer profile information 219 | * 220 | * Stores information about user (weight, stride length, etc...) 221 | */ 222 | typedef struct 223 | { 224 | /// ??? 225 | uint8_t unknown_1[2]; 226 | /// lbs times 10? i.e. 190 = {0x01, 0x90} off the device 227 | uint32_t weight; 228 | /// kg times 10? same as last 229 | uint32_t stride; 230 | /// ??? 231 | uint8_t unknown_2[2]; 232 | } omron_pd_profile_info; 233 | 234 | /** 235 | * Enumeration for count of valid pedometer information packets 236 | * 237 | * Contains the number of valid daily and hourly packets, for use by 238 | * programs for reading information off the device 239 | */ 240 | typedef struct 241 | { 242 | /// Number of valid daily packets 243 | int32_t daily_count; 244 | /// Number of valid hourly packets 245 | int32_t hourly_count; 246 | /// No idea. 247 | uint8_t unknown_1; 248 | } omron_pd_count_info; 249 | 250 | /** 251 | * Enumeration for daily data packets from pedometer 252 | * 253 | * Daily information from pedometer, including steps, distance, etc... 254 | * 255 | */ 256 | typedef struct 257 | { 258 | /// Total number of steps for the day 259 | int32_t total_steps; 260 | /// Total number of "aerobic" steps for the day 261 | int32_t total_aerobic_steps; 262 | /// Total time spent "aerobically" walking throughout the day (in minutes) 263 | int32_t total_aerobic_walking_time; 264 | /// Total calories burned kcal 265 | int32_t total_calories; 266 | /// Total distance (steps * stride) miles 267 | float total_distance; 268 | /// Total fat burned grams 269 | float total_fat_burn; 270 | /// Offset of date from current day 271 | int32_t day_serial; 272 | /// No idea 273 | uint8_t unknown_1; 274 | } omron_pd_daily_data; 275 | 276 | /** 277 | * Enumeration for hourly data packets from pedometer 278 | * 279 | * Hourly information about steps taken during a certain day 280 | */ 281 | typedef struct 282 | { 283 | /// Offset of day from current day 284 | int32_t day_serial; 285 | /// Index of hour 286 | int32_t hour_serial; 287 | /// Was anything happening for the pedometer to record? this also acts as an hour done flag for the current hour; contains 0 even if there is data 288 | uint8_t is_attached; 289 | /// Was an event recorded this hour? 290 | uint8_t event; 291 | /// Regular steps taken 292 | int32_t regular_steps; 293 | /// Aerobic steps taken 294 | int32_t aerobic_steps; 295 | } omron_pd_hourly_data; 296 | 297 | 298 | #ifdef __cplusplus 299 | extern "C" { 300 | #endif 301 | 302 | //////////////////////////////////////////////////////////////////////////////////// 303 | // 304 | // Platform Specific Functions 305 | // 306 | //////////////////////////////////////////////////////////////////////////////////// 307 | 308 | /** 309 | * Returns the number of devices connected, though does not specify device type 310 | * 311 | * @param dev Device pointer 312 | * @param VID Vendor ID, defaults to 0x0590 313 | * @param PID Product ID, defaults to 0x0028 314 | * 315 | * @return Number of devices connected, or < 0 if error 316 | */ 317 | OMRON_DECLSPEC omron_device* omron_create(); 318 | OMRON_DECLSPEC void omron_delete(omron_device* dev); 319 | 320 | /** 321 | * Returns the number of devices connected, though does not specify device type 322 | * 323 | * @param dev Device pointer 324 | * @param VID Vendor ID, defaults to 0x0590 325 | * @param PID Product ID, defaults to 0x0028 326 | * 327 | * @return Number of devices connected, or < 0 if error 328 | */ 329 | OMRON_DECLSPEC int omron_get_count(omron_device* dev, int VID, int PID); 330 | 331 | /** 332 | * Returns the number of devices connected, though does not specify device type 333 | * 334 | * @param dev Device pointer 335 | * @param device_index Index of the device to open 336 | * @param VID Vendor ID, defaults to 0x0590 337 | * @param PID Product ID, defaults to 0x0028 338 | * 339 | * @return > 0 if ok, otherwise < 0 340 | */ 341 | OMRON_DECLSPEC int omron_open(omron_device* dev, int VID, int PID, uint32_t device_index); 342 | /** 343 | * Closes an open omron device 344 | * 345 | * @param dev Device pointer to close 346 | * 347 | * @return > 0 if ok, otherwise < 0 348 | */ 349 | OMRON_DECLSPEC int omron_close(omron_device* dev); 350 | 351 | /** 352 | * Sends the control message to set a new mode for the device 353 | * 354 | * @param dev Device pointer to set mode for 355 | * @param mode Mode enumeration value, from omron_mode enum 356 | * 357 | * @return > 0 if ok, otherwise < 0 358 | */ 359 | OMRON_DECLSPEC int omron_set_mode(omron_device* dev, omron_mode mode); 360 | 361 | /** 362 | * Reads data from the device 363 | * 364 | * @param dev Device pointer to read from 365 | * @param input_report Buffer to read into (always 8 bytes) 366 | * 367 | * @return > 0 if ok, otherwise < 0 368 | */ 369 | OMRON_DECLSPEC int omron_read_data(omron_device* dev, uint8_t *input_report); 370 | 371 | /** 372 | * Writes data to the device 373 | * 374 | * @param dev Device pointer to write to 375 | * @param input_report Buffer to read from (always 8 bytes) 376 | * 377 | * @return > 0 if ok, otherwise < 0 378 | */ 379 | OMRON_DECLSPEC int omron_write_data(omron_device* dev, uint8_t *output_report); 380 | 381 | //////////////////////////////////////////////////////////////////////////////////// 382 | // 383 | // Device Information Retrieval Functions 384 | // 385 | //////////////////////////////////////////////////////////////////////////////////// 386 | 387 | /** 388 | * Retrieves the serial number of the device 389 | * 390 | * @param dev Device to get serial number from 391 | * @param data 8 byte buffer to read serial number into 392 | * 393 | * @return > 0 if ok, otherwise < 0 394 | */ 395 | OMRON_DECLSPEC int omron_get_device_serial(omron_device* dev, uint8_t* data); 396 | 397 | /** 398 | * Retrieves the version number of the device 399 | * 400 | * @param dev Device to get version number from 401 | * @param data 8 byte buffer to read version number into 402 | * 403 | * @return > 0 if ok, otherwise < 0 404 | */ 405 | OMRON_DECLSPEC int omron_get_device_version(omron_device* dev, uint8_t* data); 406 | 407 | //////////////////////////////////////////////////////////////////////////////////// 408 | // 409 | // Blood Pressure Functions 410 | // 411 | //////////////////////////////////////////////////////////////////////////////////// 412 | 413 | /** 414 | * Get profile information for pedometer 415 | * 416 | * @param dev Device to query 417 | * @param data 11 byte buffer for profile information 418 | * 419 | * @return 0 if successful, < 0 otherwise 420 | */ 421 | OMRON_DECLSPEC int omron_get_bp_profile(omron_device* dev, uint8_t* data); 422 | 423 | /** 424 | * Gets a specific data index from a specific bank of readings 425 | * 426 | * @param dev Device to query 427 | * @param bank Bank to query (A or B switch on device) 428 | * @param index Index of packet to query in bank 429 | * 430 | * @return Data packet with requested information 431 | */ 432 | OMRON_DECLSPEC omron_bp_day_info omron_get_daily_bp_data(omron_device* dev, int bank, int index); 433 | 434 | /** 435 | * Gets a specfic data index from a specific bank of readings 436 | * 437 | * @param dev Device to query 438 | * @param bank Bank to query (A or B switch on device) 439 | * @param index Index of packet to query in bank 440 | * @param evening If 0, get morning average, If 1, get evening average. 441 | * 442 | * @return Data packet with requested information 443 | */ 444 | OMRON_DECLSPEC omron_bp_week_info omron_get_weekly_bp_data(omron_device* dev, int bank, int index, int evening); 445 | 446 | //////////////////////////////////////////////////////////////////////////////////// 447 | // 448 | // Pedometer Functions 449 | // 450 | //////////////////////////////////////////////////////////////////////////////////// 451 | 452 | /** 453 | * Get pedometer profile information 454 | * 455 | * @param dev Device to query 456 | * 457 | * @return Struct with weight and stride info 458 | */ 459 | OMRON_DECLSPEC omron_pd_profile_info omron_get_pd_profile(omron_device* dev); 460 | 461 | /** 462 | * Query device for number of valid data packets 463 | * 464 | * @param dev Device to query 465 | * 466 | * @return Struct with count information 467 | */ 468 | OMRON_DECLSPEC omron_pd_count_info omron_get_pd_data_count(omron_device* dev); 469 | 470 | /** 471 | * Get data for a specific day index 472 | * 473 | * @param dev Device to query 474 | * @param day Day index, should be between 0 and info retrieved from omron_get_pd_data_count 475 | * 476 | * @return Struct with data for day 477 | */ 478 | OMRON_DECLSPEC omron_pd_daily_data omron_get_pd_daily_data(omron_device* dev, int day); 479 | 480 | /** 481 | * Get hourly data for a specific day index 482 | * 483 | * @param dev Device to query 484 | * @param day Day index, should be between 0 and info retrieved from omron_get_pd_data_count 485 | * 486 | * @return Struct with hourly info for day 487 | */ 488 | OMRON_DECLSPEC omron_pd_hourly_data* omron_get_pd_hourly_data(omron_device* dev, int day); 489 | /** 490 | * Clear the flash memory one the device 491 | * 492 | * @param dev Device to query 493 | * 494 | * @return 0 on success 495 | */ 496 | OMRON_DECLSPEC int omron_clear_pd_memory(omron_device* dev); 497 | 498 | #ifdef __cplusplus 499 | } 500 | #endif 501 | 502 | 503 | #endif //LIBOMRON_H 504 | -------------------------------------------------------------------------------- /include/win/stdint.h: -------------------------------------------------------------------------------- 1 | // ISO C9x compliant stdint.h for Microsoft Visual Studio 2 | // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 3 | // 4 | // Copyright (c) 2006-2008 Alexander Chemeris 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // 1. Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // 2. Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // 16 | // 3. The name of the author may be used to endorse or promote products 17 | // derived from this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | /////////////////////////////////////////////////////////////////////////////// 31 | 32 | #ifndef _MSC_VER // [ 33 | #error "Use this header only with Microsoft Visual C++ compilers!" 34 | #endif // _MSC_VER ] 35 | 36 | #ifndef _MSC_STDINT_H_ // [ 37 | #define _MSC_STDINT_H_ 38 | 39 | #if _MSC_VER > 1000 40 | #pragma once 41 | #endif 42 | 43 | #include 44 | 45 | // For Visual Studio 6 in C++ mode and for many Visual Studio versions when 46 | // compiling for ARM we should wrap include with 'extern "C++" {}' 47 | // or compiler give many errors like this: 48 | // error C2733: second C linkage of overloaded function 'wmemchr' not allowed 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | # include 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | // Define _W64 macros to mark types changing their size, like intptr_t. 58 | #ifndef _W64 59 | # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 60 | # define _W64 __w64 61 | # else 62 | # define _W64 63 | # endif 64 | #endif 65 | 66 | 67 | // 7.18.1 Integer types 68 | 69 | // 7.18.1.1 Exact-width integer types 70 | 71 | // Visual Studio 6 and Embedded Visual C++ 4 doesn't 72 | // realize that, e.g. char has the same size as __int8 73 | // so we give up on __intX for them. 74 | #if (_MSC_VER < 1300) 75 | typedef signed char int8_t; 76 | typedef signed short int16_t; 77 | typedef signed int int32_t; 78 | typedef unsigned char uint8_t; 79 | typedef unsigned short uint16_t; 80 | typedef unsigned int uint32_t; 81 | #else 82 | typedef signed __int8 int8_t; 83 | typedef signed __int16 int16_t; 84 | typedef signed __int32 int32_t; 85 | typedef unsigned __int8 uint8_t; 86 | typedef unsigned __int16 uint16_t; 87 | typedef unsigned __int32 uint32_t; 88 | #endif 89 | typedef signed __int64 int64_t; 90 | typedef unsigned __int64 uint64_t; 91 | 92 | 93 | // 7.18.1.2 Minimum-width integer types 94 | typedef int8_t int_least8_t; 95 | typedef int16_t int_least16_t; 96 | typedef int32_t int_least32_t; 97 | typedef int64_t int_least64_t; 98 | typedef uint8_t uint_least8_t; 99 | typedef uint16_t uint_least16_t; 100 | typedef uint32_t uint_least32_t; 101 | typedef uint64_t uint_least64_t; 102 | 103 | // 7.18.1.3 Fastest minimum-width integer types 104 | typedef int8_t int_fast8_t; 105 | typedef int16_t int_fast16_t; 106 | typedef int32_t int_fast32_t; 107 | typedef int64_t int_fast64_t; 108 | typedef uint8_t uint_fast8_t; 109 | typedef uint16_t uint_fast16_t; 110 | typedef uint32_t uint_fast32_t; 111 | typedef uint64_t uint_fast64_t; 112 | 113 | // 7.18.1.4 Integer types capable of holding object pointers 114 | #ifdef _WIN64 // [ 115 | typedef signed __int64 intptr_t; 116 | typedef unsigned __int64 uintptr_t; 117 | #else // _WIN64 ][ 118 | typedef _W64 signed int intptr_t; 119 | typedef _W64 unsigned int uintptr_t; 120 | #endif // _WIN64 ] 121 | 122 | // 7.18.1.5 Greatest-width integer types 123 | typedef int64_t intmax_t; 124 | typedef uint64_t uintmax_t; 125 | 126 | 127 | // 7.18.2 Limits of specified-width integer types 128 | 129 | #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 130 | 131 | // 7.18.2.1 Limits of exact-width integer types 132 | #define INT8_MIN ((int8_t)_I8_MIN) 133 | #define INT8_MAX _I8_MAX 134 | #define INT16_MIN ((int16_t)_I16_MIN) 135 | #define INT16_MAX _I16_MAX 136 | #define INT32_MIN ((int32_t)_I32_MIN) 137 | #define INT32_MAX _I32_MAX 138 | #define INT64_MIN ((int64_t)_I64_MIN) 139 | #define INT64_MAX _I64_MAX 140 | #define UINT8_MAX _UI8_MAX 141 | #define UINT16_MAX _UI16_MAX 142 | #define UINT32_MAX _UI32_MAX 143 | #define UINT64_MAX _UI64_MAX 144 | 145 | // 7.18.2.2 Limits of minimum-width integer types 146 | #define INT_LEAST8_MIN INT8_MIN 147 | #define INT_LEAST8_MAX INT8_MAX 148 | #define INT_LEAST16_MIN INT16_MIN 149 | #define INT_LEAST16_MAX INT16_MAX 150 | #define INT_LEAST32_MIN INT32_MIN 151 | #define INT_LEAST32_MAX INT32_MAX 152 | #define INT_LEAST64_MIN INT64_MIN 153 | #define INT_LEAST64_MAX INT64_MAX 154 | #define UINT_LEAST8_MAX UINT8_MAX 155 | #define UINT_LEAST16_MAX UINT16_MAX 156 | #define UINT_LEAST32_MAX UINT32_MAX 157 | #define UINT_LEAST64_MAX UINT64_MAX 158 | 159 | // 7.18.2.3 Limits of fastest minimum-width integer types 160 | #define INT_FAST8_MIN INT8_MIN 161 | #define INT_FAST8_MAX INT8_MAX 162 | #define INT_FAST16_MIN INT16_MIN 163 | #define INT_FAST16_MAX INT16_MAX 164 | #define INT_FAST32_MIN INT32_MIN 165 | #define INT_FAST32_MAX INT32_MAX 166 | #define INT_FAST64_MIN INT64_MIN 167 | #define INT_FAST64_MAX INT64_MAX 168 | #define UINT_FAST8_MAX UINT8_MAX 169 | #define UINT_FAST16_MAX UINT16_MAX 170 | #define UINT_FAST32_MAX UINT32_MAX 171 | #define UINT_FAST64_MAX UINT64_MAX 172 | 173 | // 7.18.2.4 Limits of integer types capable of holding object pointers 174 | #ifdef _WIN64 // [ 175 | # define INTPTR_MIN INT64_MIN 176 | # define INTPTR_MAX INT64_MAX 177 | # define UINTPTR_MAX UINT64_MAX 178 | #else // _WIN64 ][ 179 | # define INTPTR_MIN INT32_MIN 180 | # define INTPTR_MAX INT32_MAX 181 | # define UINTPTR_MAX UINT32_MAX 182 | #endif // _WIN64 ] 183 | 184 | // 7.18.2.5 Limits of greatest-width integer types 185 | #define INTMAX_MIN INT64_MIN 186 | #define INTMAX_MAX INT64_MAX 187 | #define UINTMAX_MAX UINT64_MAX 188 | 189 | // 7.18.3 Limits of other integer types 190 | 191 | #ifdef _WIN64 // [ 192 | # define PTRDIFF_MIN _I64_MIN 193 | # define PTRDIFF_MAX _I64_MAX 194 | #else // _WIN64 ][ 195 | # define PTRDIFF_MIN _I32_MIN 196 | # define PTRDIFF_MAX _I32_MAX 197 | #endif // _WIN64 ] 198 | 199 | #define SIG_ATOMIC_MIN INT_MIN 200 | #define SIG_ATOMIC_MAX INT_MAX 201 | 202 | #ifndef SIZE_MAX // [ 203 | # ifdef _WIN64 // [ 204 | # define SIZE_MAX _UI64_MAX 205 | # else // _WIN64 ][ 206 | # define SIZE_MAX _UI32_MAX 207 | # endif // _WIN64 ] 208 | #endif // SIZE_MAX ] 209 | 210 | // WCHAR_MIN and WCHAR_MAX are also defined in 211 | #ifndef WCHAR_MIN // [ 212 | # define WCHAR_MIN 0 213 | #endif // WCHAR_MIN ] 214 | #ifndef WCHAR_MAX // [ 215 | # define WCHAR_MAX _UI16_MAX 216 | #endif // WCHAR_MAX ] 217 | 218 | #define WINT_MIN 0 219 | #define WINT_MAX _UI16_MAX 220 | 221 | #endif // __STDC_LIMIT_MACROS ] 222 | 223 | 224 | // 7.18.4 Limits of other integer types 225 | 226 | #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 227 | 228 | // 7.18.4.1 Macros for minimum-width integer constants 229 | 230 | #define INT8_C(val) val##i8 231 | #define INT16_C(val) val##i16 232 | #define INT32_C(val) val##i32 233 | #define INT64_C(val) val##i64 234 | 235 | #define UINT8_C(val) val##ui8 236 | #define UINT16_C(val) val##ui16 237 | #define UINT32_C(val) val##ui32 238 | #define UINT64_C(val) val##ui64 239 | 240 | // 7.18.4.2 Macros for greatest-width integer constants 241 | #define INTMAX_C INT64_C 242 | #define UINTMAX_C UINT64_C 243 | 244 | #endif // __STDC_CONSTANT_MACROS ] 245 | 246 | 247 | #endif // _MSC_STDINT_H_ ] 248 | -------------------------------------------------------------------------------- /platform/osx/OmronNullDriver.kext/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleIdentifier 8 | com.omron.iokit.OmronDriver 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundlePackageType 12 | KEXT 13 | CFBundleSignature 14 | ???? 15 | CFBundleVersion 16 | 1.0.0 17 | IOKitPersonalities 18 | 19 | Driver1 20 | 21 | CFBundleIdentifier 22 | com.apple.kpi.iokit 23 | IOClass 24 | IOService 25 | IOProviderClass 26 | IOUSBInterface 27 | bConfigurationValue 28 | 1 29 | bInterfaceNumber 30 | 0 31 | idProduct 32 | 40 33 | idVendor 34 | 1424 35 | 36 | 37 | OSBundleLibraries 38 | 39 | com.apple.iokit.IOUSBFamily 40 | 1.8 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /platform/osx/OmronNullDriver.kext/Contents/Resources/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qdot/libomron/2687b382eac0faaa7de0f2727fc77c22514f053c/platform/osx/OmronNullDriver.kext/Contents/Resources/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /platform/osx/OmronNullDriver.kext/Contents/pbdevelopment.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PBXProjectSourcePath 6 | /Users/frank/Desktop/USBDirector/STMicro Interface Driver/STMicroInterfaceDriver.pbproj 7 | 8 | 9 | -------------------------------------------------------------------------------- /python/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | INSTALL_FILES(/python/omron ".py$") 2 | -------------------------------------------------------------------------------- /python/__init__.py: -------------------------------------------------------------------------------- 1 | # this is a python module 2 | -------------------------------------------------------------------------------- /python/device.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | 5 | def device(): 6 | 'Return omron device file name' 7 | try: 8 | return os.environ['OMRON_DEV'] 9 | except KeyError: 10 | pass 11 | 12 | from subprocess import Popen, PIPE 13 | stuff = Popen(["lsusb"],stdout=PIPE).communicate()[0] 14 | bus=None; dev=None 15 | for line in stuff.split('\n'): 16 | if not 'Omron' in line: continue 17 | line = line.split() 18 | bus = line[1][:3] 19 | dev = line[3][:3] 20 | break 21 | if bus is None or dev is None: return "" 22 | devfile='/dev/bus/usb/%s/%s'%(bus,dev) 23 | os.environ['OMRON_DEV'] = devfile 24 | return devfile 25 | 26 | if '__main__' == __name__: 27 | print device() 28 | -------------------------------------------------------------------------------- /python/gui.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | ''' 3 | Gui for reading and plotting out blood pressure values via libomron. 4 | ''' 5 | 6 | 7 | import omron 8 | import Tkinter as tk 9 | import matplotlib 10 | matplotlib.use('TkAgg') 11 | 12 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 13 | from matplotlib.figure import Figure 14 | 15 | def format_date(seconds, pos=None): 16 | import time 17 | return time.strftime('%Y-%m-%d', time.localtime(seconds)) 18 | 19 | class Gui(object): 20 | 'A simple gui for omron' 21 | def __init__(self, master, name=None, dbfile=None): 22 | self.master = master 23 | print name, dbfile 24 | # import omron 25 | # self.omron = omron.Omron() 26 | self.omron = None 27 | 28 | self.name = name 29 | 30 | self.data = None 31 | self.use_averaged = False 32 | self.use_am_pm = False 33 | self.dbfile = dbfile 34 | if self.dbfile: self.cb_open_file() 35 | 36 | # frame = tk.Frame(master) 37 | # frame.pack() 38 | 39 | menubar = tk.Menu(master) 40 | menubar.add_command(label="Quit", command = master.quit) 41 | menubar.add_command(label="Open", command = self.cb_open_file) 42 | menubar.add_command(label="Plot", command = self.cb_update_plot) 43 | menubar.add_command(label="Acquire", command = self.cb_acquire) 44 | menubar.add_command(label="Avg", command = self.cb_average) 45 | menubar.add_command(label="AM/PM", command = self.cb_am_pm) 46 | self.menubar = menubar 47 | 48 | #menubar.pack() 49 | 50 | master.config(menu=menubar) 51 | 52 | self.figure = Figure(figsize = (5,4), dpi = 100) 53 | self.canvas = FigureCanvasTkAgg(self.figure, master = master) 54 | self.canvas.show() 55 | self.canvas.get_tk_widget().pack(side = tk.TOP, fill = tk.BOTH, 56 | expand = 1) 57 | 58 | self.cb_update_plot() 59 | 60 | return 61 | 62 | def get_data(self): 63 | '''Return the current data to plot. Return a list of tuples. 64 | First value in each tuple is the time followed by 3 65 | measurements (sys,dia,pulse)''' 66 | if self.use_averaged: 67 | return self.average() 68 | return self.data.all() 69 | 70 | def cb_open_file(self): 71 | 'If given a file, open it, else prompt user' 72 | import store 73 | if self.dbfile: 74 | print 'Loading DB file %s using name %s' % (self.dbfile, self.name) 75 | self.data = store.Data(self.dbfile, self.name) 76 | return 77 | 78 | from tkFileDialog import askopenfilename 79 | self.dbfile = askopenfilename() 80 | if not self.dbfile: 81 | print 'Canceled' 82 | return 83 | return self.cb_open_file() 84 | 85 | def cb_update_plot(self): 86 | 'Update the plot given current parameters' 87 | rows = self.get_data() 88 | if not rows: return 89 | 90 | import matplotlib.ticker as ticker 91 | import time 92 | 93 | # Convert row based to column based 94 | ts1 = list() 95 | sys1 = list() 96 | dia1 = list() 97 | pulse1 = list() 98 | if self.use_am_pm: # these will be pm 99 | ts2 = list() 100 | sys2 = list() 101 | dia2 = list() 102 | pulse2 = list() 103 | pass 104 | 105 | # sort out data 106 | for row in rows: 107 | if self.use_am_pm: 108 | hour = time.localtime(row[0])[3] 109 | if hour < 12: 110 | ts1.append(row[0]) 111 | sys1.append(row[1]) 112 | dia1.append(row[2]) 113 | pulse1.append(row[3]) 114 | else: 115 | ts2.append(row[0]) 116 | sys2.append(row[1]) 117 | dia2.append(row[2]) 118 | pulse2.append(row[3]) 119 | pass 120 | continue 121 | ts1.append(row[0]) 122 | sys1.append(row[1]) 123 | dia1.append(row[2]) 124 | pulse1.append(row[3]) 125 | continue 126 | 127 | self.figure.clear() 128 | axis = self.figure.add_subplot(111) 129 | axis.plot(ts1, sys1, 'k', ts1, dia1, 'b', ts1, pulse1, 'r') 130 | if self.use_am_pm: 131 | axis.plot(ts2, sys2, 'k--', ts2, dia2, 'b--', ts2, pulse2, 'r--') 132 | axis.xaxis.set_major_formatter(ticker.FuncFormatter(format_date)) 133 | self.figure.autofmt_xdate() 134 | self.canvas.show() 135 | 136 | return 137 | 138 | def cb_acquire(self): 139 | print 'Acquiring data' 140 | import store 141 | 142 | omron_obj = omron.Omron() 143 | 144 | if omron_obj.open() < 0: 145 | print 'Failed to open device' 146 | return 147 | 148 | ret = omron_obj.get_device_version() 149 | if not ret: print 'Failed to get device version' 150 | else: print 'Opened device version %s' % ret 151 | 152 | ret = omron_obj.get_bp_profile() 153 | if not ret: print 'Failed to get device profile' 154 | else: print 'Opened device with profile: %s' % ret 155 | 156 | data_count = omron_obj.get_daily_data_count() 157 | print 'Trying to get %d readings' % data_count 158 | 159 | def bad_data(data): 160 | return not data.day and not data.month and not data.year and \ 161 | not data.hour and not data.minute and not data.second and \ 162 | not data.sys and not data.dia and not data.pulse 163 | 164 | for ind in range(data_count-1, -1, -1): 165 | for trial in range(3): 166 | bp_data = omron_obj.get_daily_bp_data(ind) 167 | if bad_data(bp_data): continue 168 | break 169 | tsec = store.ymdhms2seconds(bp_data.year, bp_data.month, 170 | bp_data.day, bp_data.hour, 171 | bp_data.minute, bp_data.second) 172 | print trial, tsec, bp_data.sys, bp_data.dia, bp_data.pulse 173 | 174 | if bad_data(bp_data): continue 175 | 176 | self.data.add(tsec, bp_data.sys, bp_data.dia, bp_data.pulse) 177 | continue 178 | 179 | self.cb_update_plot() 180 | return 181 | 182 | def average(self, window=600, data=None): 183 | 'Respond to Avg button, average nearby data in window (seconds)' 184 | if data is None: 185 | rows = self.data.all() 186 | else: 187 | rows = data 188 | new_rows = [] 189 | count = 0 190 | last_time = sys_sum = dia_sum = pulse_sum = 0 191 | for row in rows: 192 | delta_t = row[0] - last_time 193 | last_time = row[0] 194 | if delta_t > window: # save accumulated and start new with current 195 | if count: # first time through 196 | new_rows.append((last_time, sys_sum/count, dia_sum/count, 197 | pulse_sum/count)) 198 | count = 1 199 | sys_sum = row[1] 200 | dia_sum = row[2] 201 | pulse_sum = row[3] 202 | continue 203 | # we are inside window of last data, accumulate 204 | count += 1 205 | sys_sum += row[1] 206 | dia_sum += row[2] 207 | pulse_sum += row[3] 208 | continue 209 | print 'Averaged %d values down to %d' % (len(rows), len(new_rows)) 210 | return new_rows 211 | 212 | def cb_average(self): 213 | 'Toggle Avg/All' 214 | if self.use_averaged: 215 | label = 'Avg' 216 | else: 217 | label = 'All' 218 | self.menubar.entryconfig(5, label=label) 219 | self.use_averaged = not self.use_averaged 220 | self.cb_update_plot() 221 | return 222 | 223 | def cb_am_pm(self): 224 | 'Toggle AM/PM and Combined' 225 | if self.use_am_pm: 226 | label = 'AM/PM' 227 | else: 228 | label = 'Full' 229 | self.menubar.entryconfig(6, label=label) 230 | self.use_am_pm = not self.use_am_pm 231 | self.cb_update_plot() 232 | return 233 | 234 | pass 235 | 236 | 237 | class Main(object): 238 | def __init__(self, argv=None): 239 | import optparse 240 | parser = optparse.OptionParser() 241 | parser.add_option('-f', '--file', type = 'string', default = None, 242 | help = 'Set the SQLite3 data file') 243 | parser.add_option('-n', '--name', type = 'string', default = 'omron', 244 | help = 'Set a short name to distinguish the ' \ 245 | + 'data between individuals') 246 | parser.add_option('-d', '--device', type = 'string', default = None, 247 | help = 'Set the USB device file, ' \ 248 | + 'overrides OMRON_DEV environment variable') 249 | self.parser = parser 250 | if argv: 251 | self.parse_args(argv) 252 | return 253 | 254 | def parse_args(self, argv): 255 | self.opts, self.args = self.parser.parse_args(argv) 256 | return 257 | 258 | pass 259 | 260 | def run_app(): 261 | 'Run the application' 262 | import sys, os 263 | main_obj = Main(sys.argv) 264 | print main_obj.opts 265 | if main_obj.opts.device: 266 | os.environ['OMRON_DEV'] = main_obj.opts.device 267 | 268 | import device 269 | omron_dev = device.device() 270 | if omron_dev: 271 | print 'Using device: "%s"' % omron_dev 272 | else: 273 | print 'No device autodetected, try running "lsusb" and ' \ 274 | + 'setting OMRON_DEV=/dev/bus/usb/BBB/DDD' 275 | pass 276 | root = tk.Tk() 277 | app = Gui(root, main_obj.opts.name, main_obj.opts.file) 278 | root.mainloop() 279 | 280 | if '__main__' == __name__: 281 | run_app() 282 | -------------------------------------------------------------------------------- /python/omron_790IT_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import omron, store, device 4 | import os, sys 5 | 6 | print sys.path 7 | devfile = device.device() 8 | print 'Using', devfile, omron.VID, omron.PID 9 | 10 | dev = omron.create_device() 11 | print dev, dev.device._is_inited 12 | ret = omron.get_count(dev, omron.VID, omron.PID) 13 | print ret 14 | if not ret: 15 | print 'No omron device!' 16 | sys.exit(1) 17 | print 'Found %d omron'%ret 18 | 19 | o = omron.Omron() 20 | print 'Openning' 21 | ret = o.open() 22 | if ret < 0: 23 | print 'Cannot open omron 790IT' 24 | sys.exit(1) 25 | 26 | print 'Getting device version' 27 | ret = o.get_device_version() 28 | if not ret: 29 | print 'Cannot get device version!' 30 | sys.exit(1) 31 | print 'Device version: "%s"'%ret 32 | 33 | ret = o.get_bp_profile() 34 | if not ret: 35 | print 'Cannot get device prf!' 36 | sys.exit(1) 37 | print 'Device version: %s'%ret 38 | 39 | data_count = o.get_daily_data_count(); 40 | print 'AJR data count: %d'%data_count 41 | if data_count < 0: 42 | print 'Cannot get device prf!' 43 | 44 | def bad_data(r): 45 | return not r.day and not r.month and not r.year and \ 46 | not r.hour and not r.minute and not r.second and \ 47 | not r.sys and not r.dia and not r.pulse 48 | 49 | 50 | d = store.Data() 51 | for ind in range(data_count-1,-1,-1): 52 | for trial in range(3): 53 | r = o.get_daily_bp_data(ind) 54 | print ind,trial,r.year,r.month,r.day,r.hour,r.minute,r.second 55 | if bad_data(r): continue 56 | break 57 | 58 | ts = store.ymdhms2seconds(r.year,r.month,r.day,r.hour,r.minute,r.second) 59 | print trial, ts,r.sys,r.dia,r.pulse 60 | 61 | if bad_data(r): continue 62 | 63 | d.add(ts,r.sys,r.dia,r.pulse) 64 | 65 | continue 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /python/plot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | def plot(ts,sys,dia,pulse): 4 | 5 | import numpy as np 6 | import matplotlib.pyplot as plt 7 | import matplotlib.mlab as mlab 8 | import matplotlib.ticker as ticker 9 | import time 10 | 11 | def format_date(x, pos=None): 12 | return time.strftime('%Y-%m-%d',time.localtime(x)) 13 | 14 | # first we'll do it the default way, with gaps on weekends 15 | fig = plt.figure() 16 | ax = fig.add_subplot(111) 17 | ax.plot(ts, sys, 'k-', ts, dia, 'b-', ts, pulse, 'r') 18 | ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_date)) 19 | fig.autofmt_xdate() 20 | 21 | # # next we'll write a custom formatter 22 | # N = len(ts) 23 | # ind = np.arange(N) # the evenly spaced plot indices 24 | 25 | # def format_date(x, pos=None): 26 | # return time.strftime('%Y-%m-%d',time.mktime(x)) 27 | 28 | # fig = plt.figure() 29 | # ax = fig.add_subplot(111) 30 | # ax.plot(ts, sys, 'k', ts, dia, 'b', ts, pulse, 'r') 31 | # ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_date)) 32 | # fig.autofmt_xdate() 33 | 34 | plt.show() 35 | 36 | if '__main__' == __name__: 37 | import store 38 | d = store.Data() 39 | rows = d.all() 40 | timestamp = list() 41 | sys = list() 42 | dia = list() 43 | pulse = list() 44 | for row in rows: 45 | timestamp.append(row[0]) 46 | sys.append(row[1]) 47 | dia.append(row[2]) 48 | pulse.append(row[3]) 49 | 50 | plot(timestamp,sys,dia,pulse) 51 | 52 | -------------------------------------------------------------------------------- /python/store.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sqlite3, os, sys, time 4 | 5 | def ymdhms2seconds(YY,MM,DD,hh=0,mm=0,ss=0): 6 | format = "%y %m %d %H %M %S" 7 | t = time.strptime("%d %d %d %d %d %d"%(YY,MM,DD,hh,mm,ss),format) 8 | return time.mktime(t) 9 | 10 | class Data(object): 11 | def __init__(self,filename="omron.sqlite3",tablename="omron"): 12 | self.tablename = tablename 13 | self.conn = sqlite3.connect(filename) 14 | 15 | try: 16 | self.initdb(tablename) 17 | except sqlite3.OperationalError: 18 | print 'Using existing %s:%s'%(filename,tablename) 19 | else: 20 | print 'Made new %s:%s'%(filename,tablename) 21 | return 22 | 23 | def initdb(self,tablename): 24 | c = self.conn.cursor() 25 | c.execute('''create table %s 26 | (timestamp INTEGER PRIMARY KEY ON CONFLICT REPLACE, 27 | sys int, dia int, pulse int, type int)'''%tablename) 28 | self.conn.commit() 29 | c.close() 30 | return 31 | 32 | def add(self,timestamp,sys,dia,pulse,by_day = True): 33 | if by_day: by_day = 0 34 | else: by_day = 1 35 | c = self.conn.cursor() 36 | c.execute('''replace into %s values (%d,%d,%d,%d,%d)'''%\ 37 | (self.tablename,timestamp,sys,dia,pulse,by_day)) 38 | self.conn.commit() 39 | c.close() 40 | return 41 | 42 | def all(self,by_day = True): 43 | if by_day: by_day = 0 44 | else: by_day = 1 45 | c = self.conn.cursor() 46 | c.execute('select * from %s where type = %d order by timestamp'%\ 47 | (self.tablename,by_day)) 48 | ret = [] 49 | for row in c: 50 | ret.append(row) 51 | c.close() 52 | return ret 53 | 54 | pass 55 | 56 | if '__main__' == __name__: 57 | d = Data() 58 | rows = d.all() 59 | for row in rows: print row 60 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ###################################################################################### 2 | # Build function for main library 3 | ###################################################################################### 4 | 5 | SET(LIBRARY_SRCS 6 | omron.c 7 | ) 8 | 9 | IF(WIN32) 10 | LIST(APPEND LIBRARY_SRCS omron_win32.c ${LIBOMRON_INCLUDE_FILES}) 11 | ELSEIF(UNIX) 12 | LIST(APPEND LIBRARY_SRCS omron_libusb.c ${LIBOMRON_INCLUDE_FILES}) 13 | ENDIF(WIN32) 14 | 15 | INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) 16 | 17 | BUILDSYS_BUILD_LIB( 18 | NAME omron 19 | SOURCES "${LIBRARY_SRCS}" 20 | CXX_FLAGS FALSE 21 | LINK_LIBS "${LIBOMRON_REQUIRED_LIBS}" 22 | LINK_FLAGS FALSE 23 | DEPENDS FALSE 24 | SHOULD_INSTALL TRUE 25 | VERSION ${LIBOMRON_VERSION} 26 | ) 27 | -------------------------------------------------------------------------------- /src/omron.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Generic function file for Omron Health User Space Driver 3 | * 4 | * Copyright (c) 2009-2010 Kyle Machulis 5 | * 6 | * More info on Nonpolynomial Labs @ http://www.nonpolynomial.com 7 | * 8 | * Sourceforge project @ http://www.github.com/qdot/libomron/ 9 | * 10 | * This library is covered by the BSD License 11 | * Read LICENSE_BSD.txt for details. 12 | */ 13 | 14 | #include "libomron/omron.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | //#define DEBUG 22 | 23 | #ifdef DEBUG 24 | #define IF_DEBUG(x) do { x; } while (0) 25 | #else 26 | #define IF_DEBUG(x) do { } while (0) 27 | #endif 28 | 29 | #define DPRINTF(args, ...) IF_DEBUG(printf(args)) 30 | 31 | static void hexdump(uint8_t *data, int n_bytes) 32 | { 33 | while (n_bytes--) { 34 | printf(" %02x", *(unsigned char*) data); 35 | data++; 36 | } 37 | printf("\n"); 38 | } 39 | 40 | int bcd_to_int(unsigned char *data, int start, int length) 41 | { 42 | int ret = 0; 43 | int pos = start; 44 | int i; 45 | for(i = 0; i < length; ++i) 46 | { 47 | if(!(i % 2)) 48 | { 49 | if(i >= 2) 50 | pos++; 51 | ret += (data[pos] >> 4) * (pow(10, length - i - 1)); 52 | } 53 | else 54 | { 55 | ret += (data[pos] & 0x0f) * (pow(10, length - i - 1)); 56 | } 57 | } 58 | return ret; 59 | } 60 | 61 | /* 62 | * For data not starting on byte boundaries 63 | */ 64 | int bcd_to_int2(unsigned char *data, int start_nibble, int len_nibbles) 65 | { 66 | int ret = 0; 67 | int nib, abs_nib, i; 68 | for(i=0; i < len_nibbles; i++) { 69 | abs_nib = start_nibble + i; 70 | nib = (data[abs_nib / 2] >> (4 * (1 - abs_nib % 2))) & 0x0F; 71 | ret += nib * pow(10, len_nibbles - i - 1); 72 | } 73 | return ret; 74 | } 75 | 76 | short short_to_bcd(int number) 77 | { 78 | return ((number/10) << 4) | (number % 10); 79 | } 80 | 81 | 82 | int omron_send_command(omron_device* dev, int size, const unsigned char* buf) 83 | { 84 | int total_write_size = 0; 85 | int current_write_size; 86 | unsigned char output_report[8]; 87 | 88 | DPRINTF("omron_send:"); 89 | IF_DEBUG(hexdump(buf, size)); 90 | DPRINTF("\n"); 91 | 92 | while(total_write_size < size) 93 | { 94 | current_write_size = size - total_write_size; 95 | if(current_write_size > 7) 96 | current_write_size = 7; 97 | 98 | output_report[0] = current_write_size; 99 | memcpy(output_report + 1, buf+total_write_size, 100 | current_write_size); 101 | 102 | omron_write_data(dev, output_report); 103 | total_write_size += current_write_size; 104 | } 105 | 106 | return 0; 107 | } 108 | 109 | int omron_check_success(unsigned char *input_report, int start_index) 110 | { 111 | return (input_report[start_index] == 'O' && input_report[start_index + 1] == 'K') ? 0 : -1; 112 | } 113 | 114 | int omron_send_clear(omron_device* dev) 115 | { 116 | //static const unsigned char zero[23]; /* = all zeroes */ 117 | static const unsigned char zero[12]; /* = all zeroes */ 118 | //unsigned char input_report[9]; 119 | unsigned char input_report[8]; 120 | int read_result; 121 | read_result = omron_read_data(dev, input_report); 122 | do { 123 | omron_send_command(dev, sizeof(zero), zero); 124 | read_result = omron_read_data(dev, input_report); 125 | } while (omron_check_success(input_report, 1) != 0); 126 | 127 | return 0; 128 | } 129 | 130 | static int 131 | xor_checksum(unsigned char *data, int len) 132 | { 133 | unsigned char checksum = 0; 134 | 135 | unsigned int begin_len = len; 136 | 137 | while (len--) 138 | checksum ^= *(data++); 139 | 140 | if (checksum) 141 | DPRINTF("bad checksum 0x%x\n", checksum); 142 | 143 | return checksum; 144 | } 145 | 146 | /* 147 | omron_get_command_return returns: 148 | #of bytes 149 | 0 : Valid response ("OK..." or "NO"). 150 | 1 : Garbled response 151 | <0 : IO error 152 | */ 153 | 154 | int omron_get_command_return(omron_device* dev, int size, unsigned char* data) 155 | { 156 | int total_read_size = 0; 157 | int current_read_size = 0; 158 | int has_checked = 0; 159 | unsigned char input_report[9]; 160 | int read_result; 161 | 162 | 163 | DPRINTF("\n"); /* AJR */ 164 | while(total_read_size < size) 165 | { 166 | read_result = omron_read_data(dev, input_report); 167 | DPRINTF("AJR read result=%d.\n", read_result); 168 | if (read_result < 0) { 169 | fprintf(stderr, "omron_get_command_return: read_result_result %d < zero\n", read_result); 170 | return read_result; 171 | } 172 | 173 | //assert(read_result == 8); 174 | current_read_size = input_report[0]; 175 | IF_DEBUG(hexdump(input_report, current_read_size+1)); 176 | /* printf(" current_read=%d size=%d total_read_size=%d.\n", */ 177 | /* current_read_size, size, total_read_size); */ 178 | 179 | assert(current_read_size <= 8); 180 | 181 | if (current_read_size == 8) 182 | current_read_size = 7; /* FIXME? Bug? */ 183 | 184 | assert(current_read_size < 8); 185 | assert(current_read_size >= 0); 186 | 187 | assert(total_read_size >= 0); 188 | 189 | 190 | assert(current_read_size <= size - total_read_size); 191 | 192 | memcpy(data + total_read_size, input_report + 1, 193 | current_read_size); 194 | total_read_size += current_read_size; 195 | 196 | if(!has_checked && total_read_size >= 2) 197 | { 198 | if (total_read_size == 2 && 199 | data[0] == 'N' && data[1] == 'O') 200 | return 0; /* "NO" is valid response */ 201 | 202 | if (strncmp((const char*) data, "END\r\n", 203 | total_read_size) == 0) 204 | has_checked = (total_read_size >= 5); 205 | else { 206 | if (data[0] != 'O' || data[1] != 'K') 207 | return 1; /* garbled response */ 208 | 209 | has_checked = 1; 210 | } 211 | } 212 | } 213 | 214 | if (total_read_size >= 3 && data[0] == 'O' && data[1] == 'K') 215 | return xor_checksum(data+2, total_read_size-2); /* 0 = OK */ 216 | else 217 | return 0; 218 | } 219 | 220 | int omron_check_mode(omron_device* dev, omron_mode mode) 221 | { 222 | int ret; 223 | 224 | if(dev->device_mode == mode) 225 | return 0; 226 | 227 | ret = omron_set_mode(dev, mode); 228 | if(ret == 0) 229 | { 230 | dev->device_mode = mode; 231 | omron_send_clear(dev); 232 | return 0; 233 | } 234 | else 235 | { 236 | DPRINTF("omron_exchange_cmd: I/O error, status=%d\n", 237 | ret); 238 | } 239 | return ret; 240 | } 241 | 242 | static void omron_exchange_cmd(omron_device *dev, 243 | omron_mode mode, 244 | int cmd_len, 245 | const unsigned char *cmd, 246 | int response_len, 247 | unsigned char *response) 248 | { 249 | int status; 250 | struct timeval timeout; 251 | 252 | // Retry command if the response is garbled, but accept "NO" as 253 | // a valid response. 254 | do { 255 | omron_check_mode(dev, mode); 256 | omron_send_command(dev, cmd_len, cmd); 257 | status = omron_get_command_return(dev, response_len, response); 258 | if (status > 0) 259 | DPRINTF("garbled (resp_len=%d)\n", response_len); 260 | if(mode == PEDOMETER_MODE) { 261 | DPRINTF("Sleeping\n"); 262 | // Adding a short wait to see if it helps the bad data 263 | // give it 0.15 seconds to recover 264 | timeout.tv_sec = 0; 265 | timeout.tv_usec = 200000; 266 | select(0, NULL, NULL, NULL, &timeout); 267 | } 268 | } while (status > 0); 269 | 270 | if (status < 0) 271 | DPRINTF("omron_exchange_cmd: I/O error, status=%d\n", 272 | status); 273 | } 274 | 275 | static void 276 | omron_dev_info_command(omron_device* dev, 277 | const char *cmd, 278 | unsigned char *result, 279 | int result_max_len) 280 | { 281 | unsigned char* tmp = (unsigned char*)malloc(result_max_len+3); 282 | 283 | omron_exchange_cmd(dev, PEDOMETER_MODE, strlen(cmd), 284 | (const unsigned char*) cmd, 285 | result_max_len+3, tmp); 286 | 287 | memcpy(result, tmp + 3, result_max_len); 288 | free(tmp); 289 | } 290 | 291 | //platform independant functions 292 | OMRON_DECLSPEC int omron_get_device_version(omron_device* dev, unsigned char* data) 293 | { 294 | omron_dev_info_command(dev, "VER00", data, 12); 295 | data[12] = 0; 296 | return 0; 297 | } 298 | 299 | OMRON_DECLSPEC int omron_get_bp_profile(omron_device* dev, unsigned char* data) 300 | { 301 | omron_dev_info_command(dev, "PRF00", data, 11); 302 | return 0; 303 | } 304 | 305 | OMRON_DECLSPEC int omron_get_device_serial(omron_device* dev, unsigned char* data) 306 | { 307 | omron_dev_info_command(dev, "SRL00", data, 8); 308 | return 0; 309 | } 310 | 311 | //daily data information 312 | OMRON_DECLSPEC int omron_get_daily_data_count(omron_device* dev, unsigned char bank) 313 | { 314 | unsigned char data[8]; 315 | unsigned char command[8] = 316 | { 'G', 'D', 'C', 0x00, bank, 0x00, 0x00, bank }; 317 | 318 | // assert(bank < 2); 319 | omron_exchange_cmd(dev, DAILY_INFO_MODE, 8, command, 320 | sizeof(data), data); 321 | DPRINTF("Data units found: %d\n", (int)data[6]); 322 | return (int)data[6]; 323 | } 324 | 325 | OMRON_DECLSPEC omron_bp_day_info omron_get_daily_bp_data(omron_device* dev, int bank, int index) 326 | { 327 | omron_bp_day_info r; 328 | unsigned char data[17]; 329 | unsigned char command[8] = {'G', 'M', 'E', 0x00, bank, 0x00, 330 | index, index ^ bank}; 331 | 332 | memset(&r, 0 , sizeof(r)); 333 | memset(data, 0, sizeof(data)); 334 | 335 | omron_exchange_cmd(dev, DAILY_INFO_MODE, 8, command, 336 | sizeof(data), data); 337 | 338 | //printf("Daily data:"); 339 | //hexdump(data, sizeof(data)); 340 | //printf("\n"); 341 | 342 | // added by bv 343 | // if (data[0] == 'O' && data[1] == 'K') { 344 | // r.year = data[3]; 345 | // r.month = data[4]; 346 | // r.day = data[5]; 347 | // r.hour = data[6]; 348 | // r.minute = data[7]; 349 | // r.second = data[8]; 350 | // r.unknown_1[0] = data[9]; 351 | // r.unknown_1[1] = data[10]; 352 | // r.sys = data[11]; 353 | // r.dia = data[12]; 354 | // r.pulse = data[13]; 355 | // r.unknown_2[0] = data[14]; 356 | // r.unknown_2[1] = data[15]; 357 | // r.unknown_2[2] = data[16]; 358 | // } 359 | // return r; 360 | 361 | if (omron_check_success(data, 0) < 0) 362 | { 363 | r.present = 0; 364 | } 365 | else 366 | { 367 | r.present = 1; 368 | r.year = data[3]; 369 | r.month = data[4]; 370 | r.day = data[5]; 371 | r.hour = data[6]; 372 | r.minute = data[7]; 373 | r.second = data[8]; 374 | r.unknown_1[0] = data[9]; 375 | r.unknown_1[1] = data[10]; 376 | r.sys = data[11]; 377 | r.dia = data[12]; 378 | r.pulse = data[13]; 379 | r.unknown_2[0] = data[14]; 380 | r.unknown_2[1] = data[15]; 381 | r.unknown_2[2] = data[16]; 382 | } 383 | return r; 384 | } 385 | 386 | OMRON_DECLSPEC omron_bp_week_info omron_get_weekly_bp_data(omron_device* dev, int bank, int index, int evening) 387 | { 388 | omron_bp_week_info r; 389 | unsigned char data[12]; /* 12? */ 390 | unsigned char command[9] = { 'G', 391 | (evening ? 'E' : 'M'), 392 | 'A', 393 | 0, 394 | bank, 395 | index, 396 | 0, 397 | 0, 398 | index^bank }; 399 | 400 | memset(&r, 0 , sizeof(r)); 401 | memset(data, 0, sizeof(data)); 402 | 403 | omron_exchange_cmd(dev, WEEKLY_INFO_MODE, 9, command, 404 | sizeof(data), data); 405 | 406 | if (omron_check_success(data, 0) < 0) 407 | { 408 | r.present = 0; 409 | } 410 | else { 411 | r.present = 1; 412 | /* printf("Weekly data:"); */ 413 | /* hexdump(data, sizeof(data)); */ 414 | /* printf("\n"); */ 415 | 416 | r.year = data[5]; 417 | r.month = data[6]; 418 | r.day = data[7]; 419 | r.sys = data[8] + 25; 420 | r.dia = data[9]; 421 | r.pulse = data[10]; 422 | } 423 | return r; 424 | } 425 | 426 | OMRON_DECLSPEC omron_pd_profile_info omron_get_pd_profile(omron_device* dev) 427 | { 428 | unsigned char data[11]; 429 | omron_pd_profile_info profile_info; 430 | omron_dev_info_command(dev, "PRF00", data, 11); 431 | profile_info.weight = bcd_to_int(data, 2, 4) / 10; 432 | profile_info.stride = bcd_to_int(data, 6, 4) / 10; 433 | return profile_info; 434 | } 435 | 436 | OMRON_DECLSPEC int omron_clear_pd_memory(omron_device* dev) 437 | { 438 | unsigned char data[2]; 439 | omron_exchange_cmd(dev, PEDOMETER_MODE, strlen("CTD00"),"CTD00", 2, data); 440 | if((data[0]=='O') && (data[1]=='K')) { 441 | return 0; 442 | } else { 443 | return 1; 444 | } 445 | } 446 | 447 | OMRON_DECLSPEC omron_pd_count_info omron_get_pd_data_count(omron_device* dev) 448 | { 449 | omron_pd_count_info count_info; 450 | unsigned char data[5]; 451 | omron_dev_info_command(dev, "CNT00", data, 5); 452 | count_info.daily_count = data[1]; 453 | count_info.hourly_count = data[3]; 454 | return count_info; 455 | } 456 | 457 | OMRON_DECLSPEC omron_pd_daily_data omron_get_pd_daily_data(omron_device* dev, int day) 458 | { 459 | omron_pd_daily_data daily_data; 460 | unsigned char data[20]; 461 | unsigned char command[7] = 462 | { 'M', 'E', 'S', 0x00, 0x00, day, 0x00 ^ day}; 463 | 464 | // assert(bank < 2); 465 | omron_exchange_cmd(dev, PEDOMETER_MODE, sizeof(command), command, 466 | sizeof(data), data); 467 | daily_data.total_steps = bcd_to_int2(data, 6, 5); 468 | daily_data.total_aerobic_steps = bcd_to_int2(data, 11, 5); 469 | daily_data.total_aerobic_walking_time = bcd_to_int2(data, 16, 4); 470 | daily_data.total_calories = bcd_to_int2(data, 20, 5); 471 | daily_data.total_distance = bcd_to_int2(data, 25, 5) / 100.0; 472 | daily_data.total_fat_burn = bcd_to_int2(data, 30, 4) / 10.0; 473 | daily_data.day_serial = day; 474 | return daily_data; 475 | } 476 | 477 | OMRON_DECLSPEC omron_pd_hourly_data* omron_get_pd_hourly_data(omron_device* dev, int day) 478 | { 479 | omron_pd_hourly_data* hourly_data = malloc(sizeof(omron_pd_hourly_data) * 24); 480 | unsigned char data[37]; 481 | 482 | // assert(bank < 2); 483 | int i, j; 484 | for(i = 0; i < 3; ++i) 485 | { 486 | unsigned char command[8] = 487 | { 'G', 'T', 'D', 0x00, 0, day, i + 1, day ^ (i + 1)}; 488 | omron_exchange_cmd(dev, PEDOMETER_MODE, sizeof(command), command, 489 | sizeof(data), data); 490 | for(j = 0; j <= 7; ++j) 491 | { 492 | int offset = j * 4 + 4; 493 | int hour = (i * 8) + j; 494 | hourly_data[hour].is_attached = (data[(offset)] & (1 << 6)) > 0; 495 | hourly_data[hour].regular_steps = ((data[(offset)] & (~0xc0)) << 8) | (data[(offset) + 1]); 496 | hourly_data[hour].event = (data[(offset) + 2] & (1 << 6)) > 0; 497 | hourly_data[hour].aerobic_steps = ((data[(offset) + 2] & (~0xc0)) << 8) | (data[(offset) + 3]); 498 | hourly_data[hour].hour_serial = hour; 499 | hourly_data[hour].day_serial = day; 500 | } 501 | } 502 | return hourly_data; 503 | } 504 | -------------------------------------------------------------------------------- /src/omron_libusb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Generic function file for Omron Health User Space Driver - libusb version 3 | * 4 | * Copyright (c) 2009-2010 Kyle Machulis/Nonpolynomial Labs 5 | * 6 | * More info on Nonpolynomial Labs @ http://www.nonpolynomial.com 7 | * 8 | * Source code available at http://www.github.com/qdot/libomron/ 9 | * 10 | * This library is covered by the BSD License 11 | * Read LICENSE_BSD.txt for details. 12 | */ 13 | 14 | 15 | #include "libomron/omron.h" 16 | #include 17 | 18 | #define OMRON_USB_INTERFACE 0 19 | 20 | omron_device* omron_create() 21 | { 22 | omron_device* s = (omron_device*)malloc(sizeof(omron_device)); 23 | s->device._is_open = 0; 24 | s->device._is_inited = 0; 25 | if(libusb_init(&s->device._context) < 0) 26 | { 27 | return NULL; 28 | } 29 | s->device._is_inited = 1; 30 | return s; 31 | } 32 | 33 | int omron_get_count(omron_device* s, int device_vid, int device_pid) 34 | { 35 | struct libusb_device **devs; 36 | struct libusb_device *found = NULL; 37 | struct libusb_device *dev; 38 | size_t i = 0; 39 | int count = 0; 40 | 41 | if (!s->device._is_inited) 42 | { 43 | return E_NPUTIL_NOT_INITED; 44 | } 45 | 46 | if (libusb_get_device_list(s->device._context, &devs) < 0) 47 | { 48 | return E_NPUTIL_DRIVER_ERROR; 49 | } 50 | 51 | while ((dev = devs[i++]) != NULL) 52 | { 53 | struct libusb_device_descriptor desc; 54 | int dev_error_code; 55 | dev_error_code = libusb_get_device_descriptor(dev, &desc); 56 | if (dev_error_code < 0) 57 | { 58 | break; 59 | } 60 | if (desc.idVendor == device_vid && desc.idProduct == device_pid) 61 | { 62 | ++count; 63 | } 64 | } 65 | 66 | libusb_free_device_list(devs, 1); 67 | return count; 68 | } 69 | 70 | int omron_open(omron_device* s, int device_vid, int device_pid, unsigned int device_index) 71 | { 72 | int ret; 73 | struct libusb_device **devs; 74 | struct libusb_device *found = NULL; 75 | struct libusb_device *dev; 76 | size_t i = 0; 77 | int count = 0; 78 | int device_error_code = 0; 79 | 80 | if (!s->device._is_inited) 81 | { 82 | return E_NPUTIL_NOT_INITED; 83 | } 84 | 85 | if ((device_error_code = libusb_get_device_list(s->device._context, &devs)) < 0) 86 | { 87 | return E_NPUTIL_DRIVER_ERROR; 88 | } 89 | 90 | while ((dev = devs[i++]) != NULL) 91 | { 92 | struct libusb_device_descriptor desc; 93 | device_error_code = libusb_get_device_descriptor(dev, &desc); 94 | if (device_error_code < 0) 95 | { 96 | libusb_free_device_list(devs, 1); 97 | return E_NPUTIL_NOT_INITED; 98 | } 99 | if (desc.idVendor == device_vid && desc.idProduct == device_pid) 100 | { 101 | if(count == device_index) 102 | { 103 | found = dev; 104 | break; 105 | } 106 | ++count; 107 | } 108 | } 109 | 110 | if (found) 111 | { 112 | device_error_code = libusb_open(found, &s->device._device); 113 | if (device_error_code < 0) 114 | { 115 | libusb_free_device_list(devs, 1); 116 | return E_NPUTIL_NOT_INITED; 117 | } 118 | } 119 | else 120 | { 121 | return E_NPUTIL_NOT_INITED; 122 | } 123 | s->device._is_open = 1; 124 | 125 | if(libusb_kernel_driver_active(s->device._device, 0)) 126 | { 127 | libusb_detach_kernel_driver(s->device._device, 0); 128 | } 129 | ret = libusb_claim_interface(s->device._device, 0); 130 | 131 | return ret; 132 | } 133 | 134 | int omron_close(omron_device* s) 135 | { 136 | if(!s->device._is_open) 137 | { 138 | return E_NPUTIL_NOT_OPENED; 139 | } 140 | if (libusb_release_interface(s->device._device, 0) < 0) 141 | { 142 | return E_NPUTIL_NOT_INITED; 143 | } 144 | libusb_close(s->device._device); 145 | s->device._is_open = 0; 146 | return 0; 147 | } 148 | 149 | void omron_delete(omron_device* dev) 150 | { 151 | free(dev); 152 | } 153 | 154 | int omron_set_mode(omron_device* dev, omron_mode mode) 155 | { 156 | 157 | uint8_t feature_report[2] = {(mode & 0xff00) >> 8, (mode & 0x00ff)}; 158 | const uint feature_report_id = 0; 159 | const uint feature_interface_num = 0; 160 | const int REQ_HID_SET_REPORT = 0x09; 161 | const int HID_REPORT_TYPE_FEATURE = 3; 162 | int num_bytes_transferred = libusb_control_transfer(dev->device._device, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, REQ_HID_SET_REPORT, (HID_REPORT_TYPE_FEATURE << 8) | feature_report_id, feature_interface_num, feature_report, sizeof(feature_report), 1000); 163 | //We need to return 0 for success here. 164 | return !(num_bytes_transferred == sizeof(feature_report)); 165 | } 166 | 167 | int omron_read_data(omron_device* dev, uint8_t* input_report) 168 | { 169 | int trans; 170 | int ret = libusb_bulk_transfer(dev->device._device, OMRON_IN_ENDPT, input_report, 8, &trans, 1000); 171 | return ret; 172 | } 173 | 174 | int omron_write_data(omron_device* dev, uint8_t* output_report) 175 | { 176 | int trans; 177 | return libusb_bulk_transfer(dev->device._device, OMRON_OUT_ENDPT, output_report, 8, &trans, 1000); 178 | } 179 | 180 | -------------------------------------------------------------------------------- /src/omron_usbfs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "omron.h" 13 | 14 | static int omron_fd; 15 | 16 | #define TIMEOUT_MILLISECS 0 17 | 18 | #define OMRON_OUT_ENDPT 0x02 19 | #define OMRON_IN_ENDPT 0x81 20 | 21 | #define INPUT_LEN 8 22 | 23 | 24 | /* Is there some standard header file for HID protocol information? */ 25 | #define HID_REPORT_TYPE_INPUT 1 26 | #define HID_REPORT_TYPE_OUTPUT 2 27 | #define HID_REPORT_TYPE_FEATURE 3 28 | 29 | #define USB_REQ_HID_GET_REPORT 0x01 30 | #define USB_REQ_HID_SET_REPORT 0x09 31 | 32 | static const unsigned int omron_interface_num = 0; 33 | 34 | static unsigned char mk_printable(unsigned char ch) 35 | { 36 | return (ch >= ' ' && ch < 0x80) ? ch : '.'; 37 | } 38 | 39 | static void hexdump(const char *prefix, void *data_orig, int len_orig) 40 | { 41 | void *data = data_orig; 42 | int len = len_orig; 43 | 44 | #if 0 /* for debugging */ 45 | printf("%s",prefix); 46 | while (len--) { 47 | printf(" %02x", *(unsigned char*) data); 48 | data++; 49 | } 50 | 51 | printf(" "); 52 | data = data_orig; 53 | len = len_orig; 54 | while (len--) { 55 | putchar(mk_printable(*(unsigned char*) data)); 56 | data++; 57 | } 58 | printf("\n"); 59 | fflush(stdout); 60 | #endif 61 | } 62 | 63 | int omron_get_count(int VID, int PID) 64 | { 65 | return 1; 66 | } 67 | 68 | int omron_open(omron_device* dev, int VID, int PID, unsigned int device_index) 69 | { 70 | int err; 71 | const char *dev_string; 72 | 73 | dev_string = getenv("OMRON_DEV"); 74 | if (dev_string == NULL) { 75 | fprintf(stderr, "Need OMRON_DEV environment variable to be set to something like /dev/bus/usb/001/004. Do lsusb to see exactly which device.\n"); 76 | errno = ENODEV; 77 | return -1; 78 | } 79 | 80 | omron_fd = open(dev_string, O_RDWR); 81 | if (omron_fd >= 0) { 82 | const struct usbdevfs_ioctl disconnect_ioctl = { 83 | .ifno = 0, 84 | .ioctl_code = USBDEVFS_DISCONNECT, 85 | .data = NULL, 86 | }; 87 | /* OK for this ioctl to fail if there is no driver attached: */ 88 | ioctl(omron_fd, USBDEVFS_IOCTL, &disconnect_ioctl); 89 | 90 | err = ioctl(omron_fd, USBDEVFS_CLAIMINTERFACE, 91 | &omron_interface_num); 92 | if (err < 0) 93 | perror("omron_open USBDEVFS_CLAIMINTERFACE"); 94 | 95 | } 96 | return omron_fd; 97 | } 98 | 99 | int omron_close(omron_device* dev) 100 | { 101 | int err; 102 | 103 | err = ioctl(omron_fd, USBDEVFS_RELEASEINTERFACE, &omron_interface_num); 104 | if (err < 0) 105 | perror("USBDEVFS_RELEASEINTERFACE"); 106 | 107 | return close(omron_fd); 108 | } 109 | 110 | int omron_set_mode(omron_device* dev, omron_mode mode) 111 | { 112 | char feature_report[2] = {(mode & 0xff00) >> 8, (mode & 0x00ff)}; 113 | const int feature_report_id = 0; 114 | const int feature_interface_num = 0; 115 | int err; 116 | 117 | const struct usbdevfs_ctrltransfer set_mode_cmd = { 118 | /* FIXME: What is the 0x80 here symbolically? */ 119 | .bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE, 120 | .bRequest = USB_REQ_HID_SET_REPORT, 121 | .wValue = (HID_REPORT_TYPE_FEATURE << 8) | feature_report_id, 122 | .wIndex = feature_interface_num, 123 | .wLength = sizeof(feature_report), 124 | .timeout = TIMEOUT_MILLISECS, 125 | .data = feature_report, 126 | 127 | }; 128 | 129 | err = ioctl(omron_fd, USBDEVFS_CONTROL, &set_mode_cmd); 130 | if (err < 0) { 131 | perror("omron_set_mode USBDEVFS_CONTROL"); 132 | exit(1); 133 | } 134 | return 0; 135 | } 136 | 137 | int omron_read_data(omron_device* dev, unsigned char *input_report) 138 | { 139 | int result; 140 | 141 | struct usbdevfs_bulktransfer xfer = { 142 | .ep = OMRON_IN_ENDPT, 143 | .len = INPUT_LEN, 144 | .timeout= TIMEOUT_MILLISECS, 145 | .data = input_report, 146 | }; 147 | 148 | result = ioctl(omron_fd, USBDEVFS_BULK, &xfer); 149 | if (result < 0) { 150 | perror("omron_read_data USBDEVFS_BULK"); 151 | exit(1); 152 | } 153 | 154 | //hexdump("<", xfer.data, xfer.len); 155 | hexdump("<", xfer.data, ((unsigned char*) xfer.data)[0]+1); 156 | return result; 157 | } 158 | 159 | #if 0 160 | int omron_read_data_from_control(omron_device* dev, unsigned char *input_report) 161 | { 162 | const int input_report_id = 0; 163 | const int feature_interface_num = 0; 164 | int err; 165 | 166 | const struct usbdevfs_ctrltransfer get_report_cmd = { 167 | /* FIXME: What is the 0x80 here symbolically? */ 168 | .bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | 0x80, 169 | .bRequest = USB_REQ_HID_GET_REPORT, 170 | .wValue = (HID_REPORT_TYPE_INPUT << 8) | input_report_id, 171 | .wIndex = feature_interface_num, 172 | .wLength = INPUT_LEN, 173 | .timeout = TIMEOUT_MILLISECS, 174 | .data = input_report, 175 | }; 176 | 177 | memset(input_report, 0xde, 9); 178 | err = ioctl(omron_fd, USBDEVFS_CONTROL, &get_report_cmd); 179 | hexdump("<",input_report, 9); 180 | if (err < 0) { 181 | perror("omron_read_data USBDEVFS_CONTROL"); 182 | exit(1); 183 | } 184 | return INPUT_LEN; 185 | } 186 | #endif 187 | 188 | 189 | int omron_write_data(omron_device* dev, unsigned char *output_report) 190 | { 191 | int result; 192 | 193 | struct usbdevfs_bulktransfer xfer = { 194 | .ep = OMRON_OUT_ENDPT, 195 | .len = 8, /* FIXME: Make a #define */ 196 | .timeout= TIMEOUT_MILLISECS, 197 | .data = output_report, 198 | }; 199 | 200 | hexdump(">",xfer.data, xfer.len); 201 | result = ioctl(omron_fd, USBDEVFS_BULK, &xfer); 202 | if (result < 0) { 203 | perror("omron_write_data USBDEVFS_BULK"); 204 | exit(1); 205 | } 206 | 207 | return result; 208 | 209 | } 210 | -------------------------------------------------------------------------------- /src/omron_win32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Generic function file for Omron Health User Space Driver - Windows DDK version (Will not work with WDK) 3 | * 4 | * Copyright (c) 2009-2010 Kyle Machulis/Nonpolynomial Labs 5 | * 6 | * More info on Nonpolynomial Labs @ http://www.nonpolynomial.com 7 | * 8 | * Source code available at http://www.github.com/qdot/libomron/ 9 | * 10 | * This library is covered by the BSD License 11 | * Read LICENSE_BSD.txt for details. 12 | */ 13 | 14 | 15 | #include "libomron/omron.h" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | //Application global variables 23 | DWORD ActualBytesRead; 24 | DWORD BytesRead; 25 | HIDP_CAPS Capabilities; 26 | DWORD cbBytesRead; 27 | PSP_DEVICE_INTERFACE_DETAIL_DATA detailData; 28 | DWORD dwError; 29 | char FeatureReport[256]; 30 | HANDLE hEventObject; 31 | HANDLE hDevInfo; 32 | GUID HidGuid; 33 | OVERLAPPED HIDOverlapped; 34 | char InputReport[256]; 35 | ULONG Length; 36 | LPOVERLAPPED lpOverLap; 37 | BOOL MyDeviceDetected = FALSE; 38 | TCHAR* MyDevicePathName; 39 | DWORD NumberOfBytesRead; 40 | char OutputReport[256]; 41 | DWORD ReportType; 42 | ULONG Required; 43 | TCHAR* ValueToDisplay; 44 | 45 | void GetDeviceCapabilities(HANDLE DeviceHandle) 46 | { 47 | //Get the Capabilities structure for the device. 48 | 49 | PHIDP_PREPARSED_DATA PreparsedData; 50 | 51 | /* 52 | API function: HidD_GetPreparsedData 53 | Returns: a pointer to a buffer containing the information about the device's capabilities. 54 | Requires: A handle returned by CreateFile. 55 | There's no need to access the buffer directly, 56 | but HidP_GetCaps and other API functions require a pointer to the buffer. 57 | */ 58 | 59 | HidD_GetPreparsedData 60 | (DeviceHandle, 61 | &PreparsedData); 62 | 63 | /* 64 | API function: HidP_GetCaps 65 | Learn the device's capabilities. 66 | For standard devices such as joysticks, you can find out the specific 67 | capabilities of the device. 68 | For a custom device, the software will probably know what the device is capable of, 69 | and the call only verifies the information. 70 | Requires: the pointer to the buffer returned by HidD_GetPreparsedData. 71 | Returns: a Capabilities structure containing the information. 72 | */ 73 | 74 | HidP_GetCaps 75 | (PreparsedData, 76 | &Capabilities); 77 | 78 | HidD_FreePreparsedData(PreparsedData); 79 | } 80 | 81 | int omron_open_win32(omron_device* dev, int VID, int PID, unsigned int device_index, int get_count) 82 | { 83 | //Use a series of API calls to find a HID with a specified Vendor IF and Product ID. 84 | 85 | HIDD_ATTRIBUTES Attributes; 86 | SP_DEVICE_INTERFACE_DATA devInfoData; 87 | BOOL LastDevice = FALSE; 88 | int MemberIndex = 0; 89 | LONG Result; 90 | int device_count = 0; 91 | 92 | Length = 0; 93 | detailData = NULL; 94 | dev->device._dev = NULL; 95 | 96 | /* 97 | API function: HidD_GetHidGuid 98 | Get the GUID for all system HIDs. 99 | Returns: the GUID in HidGuid. 100 | */ 101 | 102 | HidD_GetHidGuid(&HidGuid); 103 | 104 | /* 105 | API function: SetupDiGetClassDevs 106 | Returns: a handle to a device information set for all installed devices. 107 | Requires: the GUID returned by GetHidGuid. 108 | */ 109 | 110 | hDevInfo=SetupDiGetClassDevs 111 | (&HidGuid, 112 | NULL, 113 | NULL, 114 | DIGCF_PRESENT|DIGCF_INTERFACEDEVICE); 115 | 116 | devInfoData.cbSize = sizeof(devInfoData); 117 | 118 | //Step through the available devices looking for the one we want. 119 | //Quit on detecting the desired device or checking all available devices without success. 120 | 121 | MemberIndex = 0; 122 | LastDevice = FALSE; 123 | 124 | do 125 | { 126 | /* 127 | API function: SetupDiEnumDeviceInterfaces 128 | On return, MyDeviceInterfaceData contains the handle to a 129 | SP_DEVICE_INTERFACE_DATA structure for a detected device. 130 | Requires: 131 | The DeviceInfoSet returned in SetupDiGetClassDevs. 132 | The HidGuid returned in GetHidGuid. 133 | An index to specify a device. 134 | */ 135 | 136 | Result=SetupDiEnumDeviceInterfaces 137 | (hDevInfo, 138 | 0, 139 | &HidGuid, 140 | MemberIndex, 141 | &devInfoData); 142 | 143 | if (Result != 0) 144 | { 145 | //A device has been detected, so get more information about it. 146 | 147 | /* 148 | API function: SetupDiGetDeviceInterfaceDetail 149 | Returns: an SP_DEVICE_INTERFACE_DETAIL_DATA structure 150 | containing information about a device. 151 | To retrieve the information, call this function twice. 152 | The first time returns the size of the structure in Length. 153 | The second time returns a pointer to the data in DeviceInfoSet. 154 | Requires: 155 | A DeviceInfoSet returned by SetupDiGetClassDevs 156 | The SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces. 157 | 158 | The final parameter is an optional pointer to an SP_DEV_INFO_DATA structure. 159 | This application doesn't retrieve or use the structure. 160 | If retrieving the structure, set 161 | MyDeviceInfoData.cbSize = length of MyDeviceInfoData. 162 | and pass the structure's address. 163 | */ 164 | 165 | //Get the Length value. 166 | //The call will return with a "buffer too small" error which can be ignored. 167 | 168 | Result = SetupDiGetDeviceInterfaceDetail 169 | (hDevInfo, 170 | &devInfoData, 171 | NULL, 172 | 0, 173 | &Length, 174 | NULL); 175 | 176 | //Allocate memory for the hDevInfo structure, using the returned Length. 177 | 178 | detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length); 179 | 180 | //Set cbSize in the detailData structure. 181 | 182 | detailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 183 | 184 | //Call the function again, this time passing it the returned buffer size. 185 | 186 | Result = SetupDiGetDeviceInterfaceDetail 187 | (hDevInfo, 188 | &devInfoData, 189 | detailData, 190 | Length, 191 | &Required, 192 | NULL); 193 | 194 | // Open a handle to the device. 195 | // To enable retrieving information about a system mouse or keyboard, 196 | // don't request Read or Write access for this handle. 197 | 198 | /* 199 | API function: CreateFile 200 | Returns: a handle that enables reading and writing to the device. 201 | Requires: 202 | The DevicePath in the detailData structure 203 | returned by SetupDiGetDeviceInterfaceDetail. 204 | */ 205 | 206 | 207 | dev->device._dev =CreateFile 208 | (detailData->DevicePath, 209 | GENERIC_READ | GENERIC_WRITE, 210 | FILE_SHARE_READ|FILE_SHARE_WRITE, 211 | (LPSECURITY_ATTRIBUTES)NULL, 212 | OPEN_EXISTING, 213 | 0, 214 | NULL); 215 | 216 | /* 217 | API function: HidD_GetAttributes 218 | Requests information from the device. 219 | Requires: the handle returned by CreateFile. 220 | Returns: a HIDD_ATTRIBUTES structure containing 221 | the Vendor ID, Product ID, and Product Version Number. 222 | Use this information to decide if the detected device is 223 | the one we're looking for. 224 | */ 225 | 226 | //Set the Size to the number of bytes in the structure. 227 | 228 | Attributes.Size = sizeof(Attributes); 229 | 230 | Result = HidD_GetAttributes 231 | (dev->device._dev, 232 | &Attributes); 233 | 234 | //Is it the desired device? 235 | 236 | MyDeviceDetected = FALSE; 237 | 238 | if ((Attributes.VendorID == VID && Attributes.ProductID == PID)) 239 | { 240 | if(get_count) 241 | { 242 | ++device_count; 243 | CloseHandle(dev->device._dev); 244 | } 245 | else 246 | { 247 | MyDeviceDetected = TRUE; 248 | MyDevicePathName = detailData->DevicePath; 249 | GetDeviceCapabilities(dev->device._dev); 250 | break; 251 | } 252 | } 253 | else 254 | { 255 | CloseHandle(dev->device._dev); 256 | } 257 | free(detailData); 258 | } //if (Result != 0) 259 | 260 | else 261 | { 262 | LastDevice=TRUE; 263 | } 264 | //If we haven't found the device yet, and haven't tried every available device, 265 | //try the next one. 266 | MemberIndex = MemberIndex + 1; 267 | } 268 | while (!LastDevice); 269 | SetupDiDestroyDeviceInfoList(hDevInfo); 270 | if(get_count) return device_count; 271 | if(MyDeviceDetected) return 0; 272 | return -1; 273 | } 274 | 275 | OMRON_DECLSPEC int omron_get_count(omron_device* dev, int VID, int PID) 276 | { 277 | return omron_open_win32(dev, VID, PID, 0, 1); 278 | } 279 | 280 | OMRON_DECLSPEC int omron_open(omron_device* dev, int VID, int PID, unsigned int device_index) 281 | { 282 | return omron_open_win32(dev, VID, PID, device_index, 0); 283 | } 284 | 285 | OMRON_DECLSPEC int omron_close(omron_device* dev) 286 | { 287 | CloseHandle(dev->device._dev); 288 | return 0; 289 | } 290 | 291 | int omron_set_mode(omron_device* dev, omron_mode mode) 292 | { 293 | char feature_report[3] = {0x0, (mode & 0xff00) >> 8, (mode & 0x00ff)}; 294 | int ret = HidD_SetFeature(dev->device._dev, feature_report, Capabilities.FeatureReportByteLength); 295 | if(!ret) 296 | { 297 | printf("Cannot send feature! %d\n", GetLastError()); 298 | return (GetLastError() * -1); 299 | } 300 | return 0; 301 | } 302 | 303 | OMRON_DECLSPEC int omron_read_data(omron_device* dev, unsigned char *input_report) 304 | { 305 | int Result; 306 | char read[9]; 307 | Result = ReadFile 308 | (dev->device._dev, 309 | read, 310 | Capabilities.InputReportByteLength, 311 | &NumberOfBytesRead, 312 | NULL); 313 | memcpy(input_report, read+1, 8); 314 | return Result; 315 | } 316 | 317 | OMRON_DECLSPEC int omron_write_data(omron_device* dev, unsigned char *output_report) 318 | { 319 | int Result; 320 | char command[9]; 321 | command[0] = 0x0; 322 | memcpy((command+1), output_report, 8); 323 | Result = WriteFile 324 | (dev->device._dev, 325 | command, 326 | Capabilities.OutputReportByteLength, 327 | &NumberOfBytesRead, 328 | (LPOVERLAPPED) &HIDOverlapped); 329 | return Result; 330 | } 331 | 332 | OMRON_DECLSPEC omron_device* omron_create() 333 | { 334 | omron_device* s = (omron_device*)malloc(sizeof(omron_device)); 335 | s->device._is_open = 0; 336 | s->device._is_inited = 1; 337 | return s; 338 | } 339 | 340 | OMRON_DECLSPEC void omron_delete(omron_device* dev) 341 | { 342 | free(dev); 343 | } 344 | -------------------------------------------------------------------------------- /swig/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Straight from the SWIG manual: 2 | # http://www.swig.org/Doc1.3/Introduction.html#Introduction%5Fbuild%5Fsystem 3 | 4 | FIND_PACKAGE(SWIG) 5 | # If we can't find SWIG, print a message saying so and don't add projects 6 | IF(NOT SWIG_FOUND) 7 | MESSAGE(STATUS "SWIG not found, not building cross language libraries!") 8 | RETURN() 9 | ENDIF() 10 | MESSAGE(STATUS "Using SWIG!") 11 | INCLUDE(${SWIG_USE_FILE}) 12 | 13 | FIND_PACKAGE(PythonLibs REQUIRED) 14 | INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) 15 | 16 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) 17 | INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) 18 | 19 | SET(CMAKE_SWIG_FLAGS "-c++") 20 | 21 | SET_SOURCE_FILES_PROPERTIES(omron.i PROPERTIES CPLUSPLUS ON) 22 | SET_SOURCE_FILES_PROPERTIES(omron.i PROPERTIES SWIG_FLAGS "-c++") 23 | 24 | # Python 25 | SWIG_ADD_MODULE(omron python omron.i Omron.cxx) 26 | SWIG_LINK_LIBRARIES(omron ${PYTHON_LIBRARIES} ${libomron_LIBRARY} ${LIBOMRON_REQUIRED_LIBS}) 27 | INSTALL_PROGRAMS(/python/omron omron.py ../lib/_omron.so) 28 | -------------------------------------------------------------------------------- /swig/Omron.cxx: -------------------------------------------------------------------------------- 1 | #include "Omron.h" 2 | Omron::~Omron() 3 | { 4 | if (device) omron_close(device); 5 | device = 0; 6 | } 7 | -------------------------------------------------------------------------------- /swig/Omron.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Simple C++ wrapper to the C API from omron.h 4 | 5 | */ 6 | #ifndef OMRON_H_SEEN 7 | #define OMRON_H_SEEN 8 | 9 | #include "libomron/omron.h" 10 | 11 | // unsigned ints are not wrapped well, so provide int versions 12 | static const int VID = OMRON_VID; 13 | static const int PID = OMRON_PID; 14 | 15 | 16 | // Not in omron.h's API? 17 | extern "C" { 18 | int omron_get_daily_data_count(omron_device* dev, unsigned char bank); 19 | } 20 | 21 | #include 22 | 23 | class Omron { 24 | omron_device* device; 25 | public: 26 | typedef std::string data; 27 | 28 | Omron() { 29 | device = omron_create(); 30 | } 31 | ~Omron(); 32 | 33 | int count(int vid=OMRON_VID, int pid=OMRON_PID) { 34 | return omron_get_count(device, vid, pid); 35 | } 36 | 37 | int open(int vid=OMRON_VID, int pid=OMRON_PID, int device_index = 0) { 38 | return omron_open(device, vid, pid, device_index); 39 | } 40 | 41 | int close() { 42 | return omron_close(device); 43 | } 44 | 45 | int set_mode(omron_mode mode) { 46 | return omron_set_mode(device, mode); 47 | } 48 | 49 | // not yet wrapped 50 | //int omron_read_data(omron_device* dev, unsigned char *input_report); 51 | //int omron_write_data(omron_device* dev, unsigned char *output_report); 52 | //int omron_get_device_serial(omron_device* dev, unsigned char* data); 53 | 54 | Omron::data get_device_version() { 55 | unsigned char buffer[30]={0}; /* buffer overflow begging to happen */ 56 | omron_get_device_version(device, buffer); 57 | return datify(buffer,30); 58 | } 59 | 60 | // Blood Pressure Functions 61 | Omron::data get_bp_profile() { 62 | unsigned char buffer[30]={0}; /* buffer overflow begging to happen */ 63 | int ret = omron_get_bp_profile(device, buffer); 64 | if (ret < 0) return Omron::data(); 65 | return datify(buffer,30); 66 | } 67 | 68 | //daily data information 69 | 70 | int get_daily_data_count(int bank = 0) { 71 | return omron_get_daily_data_count(device, bank); 72 | } 73 | 74 | // Not fully implemented 75 | // omron_bp_day_info* get_all_daily_bp_data(int* count) { 76 | // return omron_get_all_daily_bp_data(device, count); 77 | // } 78 | 79 | // Note, reversal of arguments form C API 80 | omron_bp_day_info get_daily_bp_data(int index, int bank = 0) { 81 | return omron_get_daily_bp_data(device, bank, index); 82 | } 83 | 84 | //weekly data information 85 | 86 | // Not fully implemented 87 | // omron_bp_week_info* get_all_weekly_bp_data(int* count) { 88 | // return omron_get_all_weekly_bp_data(device, count); 89 | // } 90 | 91 | // Note, reversal of arguments from C API 92 | omron_bp_week_info get_weekly_bp_data(int index, 93 | bool evening=true, int bank=0) { 94 | return omron_get_weekly_bp_data(device, bank, index, evening?1:0); 95 | } 96 | 97 | // Pedometer Functions 98 | omron_pd_profile_info get_pd_profile() { 99 | return omron_get_pd_profile(device); 100 | } 101 | omron_pd_count_info get_pd_data_count() { 102 | return omron_get_pd_data_count(device); 103 | } 104 | omron_pd_daily_data get_pd_daily_data(int day) { 105 | return omron_get_pd_daily_data(device, day); 106 | } 107 | omron_pd_hourly_data* get_pd_hourly_data(int day) { 108 | return omron_get_pd_hourly_data(device, day); 109 | } 110 | 111 | private: 112 | 113 | Omron::data datify(unsigned char* data, int maxlen) { 114 | std::string ret; 115 | for (int ind=0; ind