class HTTPRequestsBase(Retry, EnrichSignals, Block): """ A base for Blocks that makes HTTP Requests. Properties: url (str): URL to make request to. basic_auth_creds (obj): Basic Authentication credentials. http_method (select): HTTP method (ex. GET, POST, PUT, DELETE, etc). """ version = VersionProperty('0.1.0') url = Property(title='URL Target', default="http://127.0.0.1:8181", order=1) basic_auth_creds = ObjectProperty(BasicAuthCreds, title='Credentials (BasicAuth)', default=BasicAuthCreds(), advanced=True, order=4) http_method = SelectProperty(HTTPMethod, default=HTTPMethod.GET, title='HTTP Method', order=0) headers = ListProperty(Header, title="Headers", default=[], order=2) require_json = BoolProperty(title="Require JSON Response", default=False, advanced=True, order=5) verify = BoolProperty(title="Verify host's SSL certificate", default=True, advanced=True, order=7) timeout = IntProperty(title='Request Timeout', default=0, allow_none=True, advanced=True, order=6) def process_signals(self, signals): new_signals = [] for signal in signals: new_sigs = self._make_request(signal) if new_sigs: new_signals.extend(new_sigs) if new_signals: self.notify_signals(new_signals) def _make_request(self, signal): try: url = self.url(signal) except Exception as e: self.logger.warning( "Failed to evaluate url {} for incoming signal {}: {}".format( self.url.value, signal.to_dict(), e)) return timeout = self.timeout(signal) if self.timeout(signal) else None auth = self._create_auth() payload = self._create_payload(signal) headers = self._create_headers(signal) try: r = self.execute_with_retry(self._execute_request, url, auth, payload, headers, timeout) except: # out of retries for this signal return if 200 <= r.status_code < 300: return self._process_response(r, signal) else: self.logger.warning( "{} request to {} returned with response code: {}".format( self.http_method(), url, r.status_code)) return self._process_response(r, signal) def _execute_request(self, url, auth, data, headers, timeout): method = getattr(requests, self.http_method().value) self.logger.debug("Executing {} request to {} with data: {}".format( self.http_method(), url, { "auth": auth, "data": data, "headers": headers, "timeout": timeout })) return method(url, auth=auth, data=data, headers=headers, verify=self.verify(), timeout=timeout) def _process_response(self, response, signal): result = [] try: data = response.json() # if the response is a dictionary, build a signal if isinstance(data, dict): result = [self.get_output_signal(data, signal)] # if the response is a list, build a signal for each element elif isinstance(data, list): sigs = [] for s in data: sigs.append(self.get_output_signal(s, signal)) if sigs: result = sigs # otherwise, no dice on parsing the response body else: raise ValueError("Response body could not be parsed into " "Signal(s): {}".format(data)) except ValueError: if not self.require_json(): result = [ self.get_output_signal({'raw': response.text}, signal) ] else: self.logger.warning( "Request was successful, but response was not " "valid JSON. No response signal was created.") result = [signal] except Exception as e: self.logger.warning( "Request was successful but " "failed to create response signal: {}".format(e)) result = [signal] finally: # Add the rest of the Response information to the signal for sig in result: try: sig._resp = response.__dict__ except: self.logger.warning("Response failed to save to signal") self.logger.debug("{} request to {} returned with response code: " "{}. Response: {}".format( self.http_method(), self.url(signal), response.status_code, response.__dict__)) return result def _create_auth(self): if self.basic_auth_creds().username(): return requests.auth.HTTPBasicAuth( self.basic_auth_creds().username(), self.basic_auth_creds().password()) def _create_payload(self, signal): return json.dumps(signal.to_dict()) def _create_headers(self, signal): headers = {} for header in self.headers(): header_header = header.header(signal) header_value = header.value(signal) if header_header and header_value: headers[header_header] = header_value return headers
class TrackObjects(Block): version = VersionProperty('2.0.0') ipcam = BoolProperty(title='Use IP Camera?', default=False) camera = IntProperty(title='Camera Index', default=0) ipcam_address = StringProperty(title='IP Camera Address', default='', allow_none=True) video_ref = StringProperty(title='Path to video file', default='', allow_none=True) filters = ListProperty(ImageFilters, title='Filters', default=[]) def __init__(self): super().__init__() self.video_capture = None def start(self): if not self.ipcam() and self.video_ref() is None: self.video_capture = cv2.VideoCapture(0) else: self.video_capture = cv2.VideoCapture(self.video_ref()) def process_signals(self, signals): for signal in signals: try: (grabbed, frame) = self.video_capture.read() except: break if (not grabbed): break frame = imutils.resize(frame, width=600) # construct a mask and perform dialations and erosions to remove # any small blobs left in the mask for each in self.filters(): if(str(each.filter_type()) == 'hsv'): space = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) else: space = frame mask = cv2.inRange(space, tuple(each.filter_lo()), tuple(each.filter_hi())) mask = cv2.erode(mask, None, iterations=2) mask = cv2.dilate(mask, None, iterations=2) # find contours in the mask and initialize the current center cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] if len(cnts) > 0: # find the largest contour in the mask, # then use to find centroid c = max(cnts, key=cv2.contourArea) ((x, y), radius) = cv2.minEnclosingCircle(c) M = cv2.moments(c) center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"])) # only proceed if the radius meets a minimum size if radius > 10: # draw the circle/centroid on the frame & update points # NOTE: This could be removed if we don't need visual cv2.circle(frame, (int(x), int(y)), int(radius), (0, 255, 255), 2) cv2.circle(frame, center, 5, (0, 0, 255), -1) # update the points queue track_center = { 'object': each.obj(), 'x_coord': center[0], 'y_coord': center[1] } else: track_center = { 'object': each.obj(), 'x_coord': None, 'y_coord': None } sig = Signal({ "track": track_center }) self.notify_signals([sig])