Support device.screenshot() API 12/91712/1
authorDonghoon Shin <dhs.shin@samsung.com>
Tue, 11 Oct 2016 04:13:56 +0000 (13:13 +0900)
committerDonghoon Shin <dhs.shin@samsung.com>
Tue, 11 Oct 2016 04:13:56 +0000 (13:13 +0900)
Change-Id: I2b83a2e2e9698342fcf193a9fc129640d873c6b0

16 files changed:
CHANGES.txt
README.md
debian/changelog
debian/control
litmus/__init__.py
litmus/device/device.py
litmus/device/deviceartik5.py
litmus/device/devicestandalone_m0.py
litmus/device/devicestandalone_tm1.py
litmus/device/devicestandalone_tm2.py
litmus/device/devicestandalone_tw1.py
litmus/device/devicestandalone_u3.py
litmus/device/devicestandalone_xu3.py
litmus/device/devicestandalone_z1.py
litmus/device/deviceu3.py
litmus/helper/helper.py

index 5655b55f5c2df92ef4f47892895b05ddc90d1c3f..9da8bc42451a93901118a8c986483e221be0dc9c 100644 (file)
@@ -39,3 +39,7 @@ Version 0.3.1   22 Sep 2016
 Version 0.3.2   07 Oct 2016
 ---------------------------
 - Support artik and more standalone device types
+
+Version 0.3.3   11 Oct 2016
+---------------------------
+- Support device.screenshot() API
index 179460a3075db0c3ecbe52c00afd629bab367ab8..a5124e44838bbbeb5f3efd8c993f7b58f7f0ba38 100644 (file)
--- a/README.md
+++ b/README.md
@@ -35,7 +35,7 @@ Buliding & installing
 
    $ cd ..
    
-   $ sudo dpkg -i litmus_0.3.1-1_amd64.deb
+   $ sudo dpkg -i litmus_0.3.3-1_amd64.deb
 
 
 Getting started
index 48b9aa1cf67f0085f941273fb5703e170dc6c96b..63cb7d0e57e1864217e1af02df418e9e0e9d7388 100644 (file)
@@ -1,3 +1,9 @@
+litmus (0.3.3-1) unstable; urgency=low
+
+  * Support device.screenshot API
+
+ -- Donghoon Shin <dhs.shin@samsung.com>  Tue, 11 Oct 2016 12:41:00 +0900
+
 litmus (0.3.2-1) unstable; urgency=low
 
   * Support artik and more standalone device types
index ab231637e3dff9c9dafb343b956b0506b210595e..2d2d43cb5753013e83ff620c587ab0e9ec184efe 100644 (file)
@@ -15,9 +15,11 @@ Depends: ${python3:Depends}, ${misc:Depends},
  python3-yaml (>= 3.10),
  python3-requests (>= 2.2.1),
  python3-bs4 (>= 4.2.1),
+ python3-pil (>= 2.3.0),
  python3-fasteners (>= 0.12),
  git (>= 1.9),
  lthor (>= 2.0),
+ imagemagick (>= 6.7.7),
  clewarecontrol (>= 4.1),
  smartpower (>= 0.1),
  heimdall-flash (>= 1.4.1-2),
index 131d9e3edb74e0f7024169d91f4c64ea6a9dfec5..9a396a841091cc006bcb18b88eeec38533b612ba 100644 (file)
@@ -14,7 +14,7 @@
 # limitations under the License.
 import os
 
-__version__ = '0.3.2'
+__version__ = '0.3.3'
 _homedir_ = os.path.expanduser('~')
 _confdir_ = os.path.join(_homedir_, '.litmus')
 _duts_ = os.path.join(_confdir_, 'topology')
index 981f7d51c9dce9957747f831af59679ccda5bcf6..2908898e9bab432c912120688edd02c6421b12e8 100644 (file)
@@ -17,7 +17,9 @@ import os
 import time
 import serial
 import logging
+import tempfile
 import fasteners
+from PIL import Image
 from threading import Thread, Lock
 from litmus.core.util import call, check_output
 from litmus.core.util import convert_single_item_to_list
@@ -52,6 +54,8 @@ class device(object):
     _max_attempt_boot_retry = 3
     _boot_timeout = 50.0
     _path_for_locks = _path_for_locks_
+    _screen_width = 1920
+    _screen_height = 1080
 
     _cutter = None
     _uart = None
@@ -349,7 +353,86 @@ class device(object):
             elif isinstance(l['args'], tuple):
                 l['func'](self, *l['args'])
 
+    def screenshot(self, filename):
+        """
+        Take a screenshot (png format)
+
+        :param str filename: screenshot file name
+
+        Example:
+            >>> dut.screenshot('screenshot.png')
+
+        """
+        logging.debug('==== Take a screenshot: {}, width: {}, height: {} ===='
+                      .format(filename,
+                              self._screen_width,
+                              self._screen_height))
+        dt = self._get_display_server_type()
+        if dt == 'X11':
+            self._screenshot_x11(filename)
+        elif dt == 'WAYLAND':
+            self._screenshot_wayland(filename)
+
     # private methods.
+    def _get_display_server_type(self):
+        """docstring for get_display_server_type"""
+        res = self.run_cmd('ls /usr/lib', timeout=10)
+        if find_pattern('.*libX11.*', res):
+            return 'X11'
+        else:
+            return 'WAYLAND'
+
+    def _screenshot_x11(self, filename):
+        """docstring for _screenshot_x11"""
+        # take a screenshot using xwd
+        cmd = 'xwd -root -out /tmp/{}.xwd'.format(filename)
+        self.run_cmd(cmd, timeout=20)
+
+        # pull xwd file
+        self.pull_file('/tmp/{}.xwd'.format(filename), os.curdir, timeout=20)
+
+        # convert xwd to png and resize it
+        call(['convert', '{0}.xwd'.format(filename), '-resize',
+              '{0}x{1}'.format(self._screen_width, self._screen_height),
+              filename], timeout=20)
+        call(['rm', '{}.xwd'.format(filename)], timeout=20)
+
+    def _screenshot_wayland(self, filename):
+        """docstring for _screenshot_wayland"""
+        # Find all viewable window id
+        p_winid = '.*(0x[a-zA-Z0-9]{8})\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)\s+(\d+).*\sViewable.*'
+        winids = find_all_pattern(p_winid,
+                                  self.run_cmd('enlightenment_info -topvwins',
+                                               timeout=20))
+        if winids:
+            # Dump windows
+            outs = self.run_cmd('enlightenment_info -dump_topvwins',
+                                timeout=20)
+            dirn = find_pattern('directory:\s(.*)',
+                                outs,
+                                groupindex=1).rstrip()
+
+            # Create tempdir and pull dump files
+            tmpdir = tempfile.mkdtemp()
+            self.pull_file(dirn, tmpdir, timeout=20)
+
+            # If dump does not exist then remove winid from list
+            winids = [winid for winid in winids
+                      if os.path.exists(os.path.join(tmpdir, winid[0]+'.png'))]
+
+            # Base image
+            bg = Image.new('RGB', (self._screen_width, self._screen_height))
+            # Merge images
+            for winid in reversed(winids):
+                try:
+                    fg = Image.open(os.path.join(tmpdir, winid[0]+'.png'))
+                    bg.paste(fg, (int(winid[1]), int(winid[2])), fg)
+                except FileNotFoundError:
+                    pass
+            # Save merged image
+            bg.save(filename)
+            # Remove tempdir
+            call(['rm', '-rf', tmpdir], timeout=10)
 
     def _flush_uart_buffer(self):
         """docstring for flush_uart_buffer"""
index bc4323eaa0011be87b32297b9cc3d003288ebb30..15129af457a82824f3fe3c2c12f7f47c220fbb71 100644 (file)
@@ -19,3 +19,5 @@ from litmus.device.deviceartik10 import deviceartik10
 class deviceartik5(deviceartik10):
     """docstring for device"""
     _pattern_bootprompt = r'ARITK.*# .*'
+    _screen_width = 480
+    _screen_height = 800
index 41cc55658a0d11b3d185f998145a594465274f82..6306d89d8541099bd40475016734cbe7f29dccc4 100644 (file)
@@ -18,5 +18,5 @@ from litmus.device.devicestandalone import devicestandalone
 
 class devicestandalone_m0(devicestandalone):
     """docstring for device"""
-    pass
-
+    _screen_width = 720
+    _screen_height = 1280
index 0cada0794f62364163400da468b2d43612433092..b6f9a7ef3defd454f08872f6e769dab687c2c08e 100644 (file)
@@ -18,5 +18,5 @@ from litmus.device.devicestandalone import devicestandalone
 
 class devicestandalone_tm1(devicestandalone):
     """docstring for device"""
-    pass
-
+    _screen_width = 720
+    _screen_height = 1280
index 79cb68b09f7a0d6f8ea10fbd979ab0c6d3fdcda6..208a7d5791c6e5b95e6e1804d54ca8d1fe86870a 100644 (file)
@@ -18,5 +18,5 @@ from litmus.device.devicestandalone import devicestandalone
 
 class devicestandalone_tm2(devicestandalone):
     """docstring for device"""
-    pass
-
+    _screen_width = 1440
+    _screen_height = 2560
index fe459e8444b5a9ae47f361b3e9da7c8d29300d90..774a250472a84291415f7bf7dcb2fb9a7af5cc12 100644 (file)
@@ -18,5 +18,5 @@ from litmus.device.devicestandalone import devicestandalone
 
 class devicestandalone_tw1(devicestandalone):
     """docstring for device"""
-    pass
-
+    _screen_width = 360
+    _screen_height = 360
index 9517b1eb69a2a352c4d6503575718260a286906b..eae7668ea23e9354c011398b68f97d7ceffba607 100644 (file)
@@ -19,4 +19,3 @@ from litmus.device.devicestandalone import devicestandalone
 class devicestandalone_u3(devicestandalone):
     """docstring for device"""
     pass
-
index 08bc42081df408c1e4316f5be5aba9fb9a14dab4..44d8206a60866d22af069daa381d01f960fdc791 100644 (file)
@@ -19,4 +19,3 @@ from litmus.device.devicestandalone import devicestandalone
 class devicestandalone_xu3(devicestandalone):
     """docstring for device"""
     pass
-
index 8a85f76a3323dabdbab6604ba7837a711ee42e6b..a4e61f58ee5f85b7b81489c317dd63ac9906acec 100644 (file)
@@ -18,5 +18,5 @@ from litmus.device.devicestandalone import devicestandalone
 
 class devicestandalone_z1(devicestandalone):
     """docstring for device"""
-    pass
-
+    _screen_width = 480
+    _screen_height = 800
index 9c5d399f8fc09863da6be062c8c524d9367ff88d..a8687d3e547319c02f57f8a3687c7cb4312930db 100644 (file)
@@ -19,4 +19,3 @@ from litmus.device.device import device
 class deviceu3(device):
     """docstring for device"""
     pass
-
index 26a8cf2a4e0927c2c2996112b49304526be084f8..0b4eac3a468bf128d86947e87f083115e7eae56e 100644 (file)
@@ -18,7 +18,6 @@ import sys
 import time
 import logging
 import requests
-import litmus
 import urllib.parse
 from bs4 import BeautifulSoup
 from litmus.core.util import find_pattern, find_all_pattern
@@ -173,7 +172,6 @@ def install_plugin(dut, script, waiting=5, timeout=180):
     dut.off()
 
 
-import os
 import tempfile
 import shutil
 from subprocess import DEVNULL