tchellomello / python-amcrest

A Python 2.7/3.x module for Amcrest and Dahua Cameras using the SDK HTTP API.
GNU General Public License v2.0
214 stars 75 forks source link

Event stream parsing cannot handle arrays #204

Closed bdevel closed 2 years ago

bdevel commented 2 years ago

It seems the _build_payload function in src/amcrest/event.py cannot handle JSON style arrays as provided by my camera event stream.

Package: amcrest==1.9.3

Camera Details:

{'device_name': 'xxxxxxxx',
 'device_type': 'IP8M-T2669E-AI',
 'sw_version': '2.800.00AC000.0.R',
 'version': '1.0.15'}

Event as seen by curl:

--myboundary
Content-Type: text/plain
Content-Length:218

Code=SmartMotionVehicle;action=Start;index=0;data={
   "RegionName" : [ "Driveway" ],
   "WindowId" : [ 0 ],
   "object" : [
      {
         "Rect" : [ 104, 2320, 1232, 4048 ],
         "VehicleID" : 0
      }
   ]
}

Parsed as:

{'Code': 'SmartMotionVehicle',
 'action': 'Start',
 'data': {'Rect': '[',
          'RegionName': '[',
          'VehicleID': '0',
          'WindowId': '[',
          'object': '['},
 'index': '0'}

Issue, 'RegionName' value is parsed as '[' where [ "Driveway" ] would be expected.

Another example event:

--myboundary
Content-Type: text/plain
Content-Length:795

Code=CrossLineDetection;action=Stop;index=0;data={
   "Class" : "Normal",
   "CountInGroup" : 1,
   "DetectLine" : [
      [ 3349, 1776 ],
      [ 3349, 4033 ]
   ],
   "Direction" : "LeftToRight",
   "EventID" : 14637,
   "GroupID" : 32,
   "Name" : "Road heading north",
   "Object" : {
      "Action" : "Appear",
      "BoundingBox" : [ 2312, 1624, 3768, 2712 ],
      "BrandYear" : 0,
      "CarLogoIndex" : 0,
      "Category" : "Unknown",
      "Center" : [ 3040, 2168 ],
      "Confidence" : 0,
      "MainColor" : [ 0, 0, 0, 0 ],
      "ObjectID" : 170819,
      "ObjectType" : "Vehicle",
      "RelativeID" : 0,
      "Speed" : 0,
      "SubBrand" : 0,
      "Text" : "Unknown"
   },
   "PTS" : 49945272770.0,
   "RuleID" : 5,
   "Track" : [],
   "UTC" : 1641378155,
   "UTCMS" : 256
}

Parsed as:

{'Code': 'CrossLineDetection',
 'action': 'Stop',
 'data': {'Action': 'Appear',
          'BoundingBox': '[',
          'BrandYear': '0,',
          'CarLogoIndex': '0,',
          'Category': 'Unknown',
          'Center': '[',
          'Class': 'Normal',
          'Confidence': '0,',
          'CountInGroup': '1,',
          'DetectLine': '[',
          'Direction': 'LeftToRight',
          'EventID': '14637,',
          'GroupID': '32,',
          'MainColor': '[',
          'Name': 'Road heading north',
          'Object': '{',
          'ObjectID': '170819,',
          'ObjectType': 'Vehicle',
          'PTS': '49945272770.0,',
          'RelativeID': '0,',
          'RuleID': '5,',
          'Speed': '0,',
          'SubBrand': '0,',
          'Text': 'Unknown',
          'Track': '[],',
          'UTC': '1641378155,',
          'UTCMS': '256'},
 'index': '0'}

From what I see in my camera, it may be safe to assume data={ can parse as JSON.

rkben commented 2 years ago

would a try/except json.loads() on data={...} and fall back to regex; be appropriate?

edit: drop mention

flacjacket commented 2 years ago

I think something like that seems reasonable. I'm not sure what the original regex is designed to accomplish, it was added in #162 to handle the AD110. As long as there is a good way to handle this while not breaking the doorbell functionality, that would be great. I don't have one to test, though.

flacjacket commented 2 years ago

I think this is addressed in #212 that makes the change to be able to json.loads the data in.