\r\n

51Degrees Device Detection Python  4.4

Device Detection services for 51Degrees Pipeline

cloud/gettingstarted_console.py

This example shows how to use the 51Degrees Cloud service to determine details about a device based on its User-Agent and User-Agent Client Hint HTTP header values.

You will learn:

  1. How to create a Pipeline that uses the 51Degrees cloud service
  2. How to pass input data (evidence) to the Pipeline
  3. How to retrieve the results

This example is available in full on GitHub.

To run this example, you will need to create a resource key. The resource key is used as shorthand to store the particular set of properties you are interested in as well as any associated license keys that entitle you to increased request limits and/or paid-for properties.

You can create a resource key using the 51Degrees Configurator.

Required PyPi Dependencies:

  • fiftyone_devicedetection
1 # *********************************************************************
2 # This Original Work is copyright of 51 Degrees Mobile Experts Limited.
3 # Copyright 2022 51 Degrees Mobile Experts Limited, Davidson House,
4 # Forbury Square, Reading, Berkshire, United Kingdom RG1 3EU.
5 #
6 # This Original Work is licensed under the European Union Public Licence
7 # (EUPL) v.1.2 and is subject to its terms as set out below.
8 #
9 # If a copy of the EUPL was not distributed with this file, You can obtain
10 # one at https://opensource.org/licenses/EUPL-1.2.
11 #
12 # The 'Compatible Licences' set out in the Appendix to the EUPL (as may be
13 # amended by the European Commission) shall be deemed incompatible for
14 # the purposes of the Work and the provisions of the compatibility
15 # clause in Article 5 of the EUPL shall not apply.
16 #
17 # If using the Work as, or as part of, a network application, by
18 # including the attribution notice(s) required under Article 5 of the EUPL
19 # in the end user terms of the application under an appropriate heading,
20 # such notice(s) shall fulfill the requirements of that article.
21 # *********************************************************************
22 
23 
34 
35 import json5
36 from pathlib import Path
37 import sys
38 from fiftyone_devicedetection.devicedetection_pipelinebuilder import DeviceDetectionPipelineBuilder
39 from fiftyone_pipeline_core.logger import Logger
40 from fiftyone_pipeline_core.pipelinebuilder import PipelineBuilder
41 from ..example_utils import ExampleUtils
42 
43 class GettingStartedConsole():
44  def run(self, config, logger, output):
45 
46  # In this example, we use the PipelineBuilder and configure it from a file.
47  # For more information about builders in general see the documentation at
48  # http://51degrees.com/documentation/_concepts__configuration__builders__index.html
49 
50  # Create the pipeline using the service provider and the configured options.
51  pipeline = PipelineBuilder().add_logger(logger).build_from_configuration(config)
52 
53  # carry out some sample detections
54  for values in self.EvidenceValues:
55  self.analyseEvidence(values, pipeline, output)
56 
57  def analyseEvidence(self, evidence, pipeline, output):
58 
59  # FlowData is a data structure that is used to convey
60  # information required for detection and the results of the
61  # detection through the pipeline.
62  # Information required for detection is called "evidence"
63  # and usually consists of a number of HTTP Header field
64  # values, in this case represented by a dictionary of header
65  # name/value entries.
66  data = pipeline.create_flowdata()
67 
68  message = []
69 
70  # List the evidence
71  message.append("Input values:\n")
72  for key in evidence:
73  message.append(f"\t{key}: {evidence[key]}\n")
74 
75  output("".join(message))
76 
77  # Add the evidence values to the flow data
78  data.evidence.add_from_dict(evidence)
79 
80  # Process the flow data.
81  data.process()
82 
83  message = []
84  message.append("Results:\n")
85 
86  # Now that it's been processed, the flow data will have
87  # been populated with the result. In this case, we want
88  # information about the device, which we can get by
89  # asking for a result matching named "device"
90  device = data.device
91 
92  # Display the results of the detection, which are called
93  # device properties. See the property dictionary at
94  # https://51degrees.com/developers/property-dictionary
95  # for details of all available properties.
96  self.outputValue("Mobile Device", device.ismobile, message)
97  self.outputValue("Platform Name", device.platformname, message)
98  self.outputValue("Platform Version", device.platformversion, message)
99  self.outputValue("Browser Name", device.browsername, message)
100  self.outputValue("Browser Version", device.browserversion, message)
101  output("".join(message))
102 
103  def outputValue(self, name, value, message):
104  # Individual result values have a wrapper called
105  # `AspectPropertyValue`. This functions similarly to
106  # a null-able type.
107  # If the value has not been set then trying to access the
108  # `value` method will throw an exception.
109  # `AspectPropertyValue` also includes the `no_value_message`
110  # method, which describes why the value has not been set.
111  message.append(
112  f"\t{name}: {value.value()}\n" if value.has_value()
113  else f"\t{name}: {value.no_value_message()}\n")
114 
115 
116  # This collection contains the various input values that will
117  # be passed to the device detection algorithm.
118  EvidenceValues = [
119  # A User-Agent from a mobile device.
120  { "header.user-agent":
121  "Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G960U) "
122  "AppleWebKit/537.36 (KHTML, like Gecko) "
123  "SamsungBrowser/10.1 Chrome/71.0.3578.99 Mobile Safari/537.36" },
124  # A User-Agent from a desktop device.
125  { "header.user-agent":
126  "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
127  "AppleWebKit/537.36 (KHTML, like Gecko) "
128  "Chrome/78.0.3904.108 Safari/537.36" },
129  # Evidence values from a windows 11 device using a browser
130  # that supports User-Agent Client Hints.
131  { "header.user-agent":
132  "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
133  "AppleWebKit/537.36 (KHTML, like Gecko) "
134  "Chrome/98.0.4758.102 Safari/537.36",
135  "header.sec-ch-ua-mobile": "?0",
136  "header.sec-ch-ua":
137  "\" Not A; Brand\";v=\"99\", \"Chromium\";v=\"98\", "
138  "\"Google Chrome\";v=\"98\"",
139  "header.sec-ch-ua-platform": "\"Windows\"",
140  "header.sec-ch-ua-platform-version": "\"14.0.0\"" }
141  ]
142 
143 def main(argv):
144  # Use the command line args to get the resource key if present.
145  # Otherwise, get it from the environment variable.
146  resource_key = argv[0] if len(argv) > 0 else ExampleUtils.get_resource_key()
147 
148  # Configure a logger to output to the console.
149  logger = Logger(min_level="info")
150 
151  # Load the configuration file
152  configFile = Path(__file__).resolve().parent.joinpath("gettingstarted_console.json").read_text()
153  config = json5.loads(configFile)
154 
155  # Get the resource key setting from the config file.
156  resourceKeyFromConfig = ExampleUtils.get_resource_key_from_config(config)
157  configHasKey = resourceKeyFromConfig and resourceKeyFromConfig.startswith("!!") == False
158 
159  # If no resource key is specified in the config file then override it with the key
160  # from the environment variable / command line.
161  if configHasKey == False:
162  ExampleUtils.set_resource_key_in_config(config, resource_key)
163 
164  # If we don't have a resource key then log an error.
165  if not ExampleUtils.get_resource_key_from_config(config):
166  logger.log("error",
167  "No resource key specified in the configuration file " +
168  "'gettingstarted_console.json' or the environment variable " +
169  f"'{ExampleUtils.RESOURCE_KEY_ENV_VAR}'. The 51Degrees cloud " +
170  "service is accessed using a 'ResourceKey'. For more information " +
171  "see " +
172  "http://51degrees.com/documentation/_info__resource_keys.html. " +
173  "A resource key with the properties required by this example can be " +
174  "created for free at https://configure.51degrees.com/1QWJwHxl. " +
175  "Once complete, populate the config file or environment variable " +
176  "mentioned at the start of this message with the key.")
177  else:
178  GettingStartedConsole().run(config, logger, print)
179 
180 if __name__ == "__main__":
181  main(sys.argv[1:])