Explorar el Código

Merged in FD3-622 (pull request #36)

Vista CM y actualización de comando en los vendors.
Maximiliano Schvindt hace 7 años
padre
commit
fe23dd2663

+ 2 - 2
composer.lock

@@ -1580,7 +1580,7 @@
             "source": {
                 "type": "git",
                 "url": "ssh://git@gogs.infra.flowdat.com:222/VendorSoftwareFlowdat3/RedisBundle.git",
-                "reference": "ec6e2cfcd148357264fab528aaca8641736605d3"
+                "reference": "e7ac03ffd884b57cfd8fcf7a14c1d3f2b3b47d80"
             },
             "require": {
                 "predis/predis": "^1.1"
@@ -1596,7 +1596,7 @@
                 "php-redis-service",
                 "redis"
             ],
-            "time": "2018-07-05T17:19:01+00:00"
+            "time": "2018-07-11T17:32:59+00:00"
         },
         {
             "name": "ik/stats/base-stats-bundle",

+ 3 - 17
src/StatsBundle/Admin/CablemodemAdmin.php

@@ -114,25 +114,11 @@ class CablemodemAdmin extends BaseAdmin
      */
     protected function configureShowFields(ShowMapper $showMapper)
     {
-        $interface = $this->getSubject();
-        $cmtsDeviceId = $interface->getCmtsDeviceId();
-        $deviceServer = $interface->getDeviceServer();
-        
-        $em = $this->get("doctrine.orm.entity_manager");
+        $from = $this->getRequest()->get('from');
+        $to = $this->getRequest()->get('to');
 
-        $cmts = $em->getRepository("StatsBundle:device")->findOneBy(array('deviceId' => $cmtsDeviceId, 'deviceServer'=>$deviceServer, 'deviceType' => 'CablemodemBundle\Entity\CMTS'));
-        if($cmts) {
-            $data = $cmts->jsonExtraData();
-            $cmtsName = null;
-            if(isset($data['name'])) $cmtsName = $data['name'];
-        }
+        $this->parameters = array('from' => $from, 'to' => $to);
 
-        $showMapper
-        ->add('cmtsDeviceId', 'string', array('template' => 'StatsBundle:CmtsInterface:base_show_field_cmts.html.twig','cmtsName' => $cmtsName))
-        ->add('ip')
-        ->add('mac')
-        //->add('jsonExtraData', 'string', array('template' => 'StatsBundle:CmtsInterface:field_extra_data.html.twig', 'extend' => 'base_show_field.html.twig'))
-        ;
     }
 
     /**

+ 7 - 8
src/StatsBundle/Command/StatsCmCommand.php

@@ -76,7 +76,6 @@ class StatsCmCommand extends BaseCommand
 
             if(isset($cmsStats[$mac])) $stats = json_decode($cmsStats[$mac],true); 
             
-            
             $row['id'] = "NULL";
             $row['deviceServer'] = $cmtsServerId;
             $row['cmtsDeviceId'] = $cmtsDeviceId;
@@ -96,13 +95,13 @@ class StatsCmCommand extends BaseCommand
             $row['downIf'] = "'{$info['downInterface']}'";
             $row['status'] = $info['status'];
             
-            (isset($stats['txPower']))? $row['txPower'] = $stats['txPower'][2] : $row['txPower'] = "NULL";
-            (isset($stats['rxPower']))? $row['rxPower'] = $stats['rxPower'][3] : $row['rxPower'] = "NULL";
-            (isset($stats['signal']))? $row['signal'] = $stats['signal'][3] : $row['signal'] = "NULL";
-            (isset($stats['microreflection']))? $row['microreflection'] = $stats['microreflection'][3] : $row['microreflection'] = "NULL";
-            (isset($stats['unerroreds']))? $row['unerroreds'] = $stats['unerroreds'][3] : $row['unerroreds'] = "NULL";
-            (isset($stats['correcteds']))? $row['correcteds'] = $stats['correcteds'][3] : $row['correcteds'] = "NULL";
-            (isset($stats['uncorrectables']))? $row['uncorrectables'] = $stats['uncorrectables'][3] : $row['uncorrectables'] = "NULL";
+            (isset($stats['txPower'][2]))? $row['txPower'] = $stats['txPower'][2] : $row['txPower'] = "NULL";
+            (isset($stats['rxPower'][3]))? $row['rxPower'] = $stats['rxPower'][3] : $row['rxPower'] = "NULL";
+            (isset($stats['signal'][3]))? $row['signal'] = $stats['signal'][3] : $row['signal'] = "NULL";
+            (isset($stats['microreflection'][3]))? $row['microreflection'] = $stats['microreflection'][3] : $row['microreflection'] = "NULL";
+            (isset($stats['unerroreds'][3]))? $row['unerroreds'] = $stats['unerroreds'][3] : $row['unerroreds'] = "NULL";
+            (isset($stats['correcteds'][3]))? $row['correcteds'] = $stats['correcteds'][3] : $row['correcteds'] = "NULL";
+            (isset($stats['uncorrectables'][3]))? $row['uncorrectables'] = $stats['uncorrectables'][3] : $row['uncorrectables'] = "NULL";
             (isset($stats['uptime']))? $row['uptime'] = "'{$stats['uptime']}'" : $row['uptime'] = "NULL";
             
             $row['updated'] = "'".date("Y-m-d H:i:s")."'";

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 158 - 8
src/StatsBundle/Controller/StatsController.php


+ 1 - 1
src/StatsBundle/Resources/config/services.yml

@@ -61,7 +61,7 @@ services:
         calls:
             - [setTranslationDomain, [StatsBundle]]
             - [setTemplate, ['outer_list_rows_list','StatsBundle:Templates:list_outer_rows_list.html.twig']]
-            - [setTemplate, ['show','StatsBundle:Cablemodem:base_show.html.twig']]
+            - [setTemplate, ['show','StatsBundle:Cablemodem:base_show_v2.html.twig']]
 
     sonata.admin.stats.cmts_interface:
         class: StatsBundle\Admin\CmtsInterfaceAdmin

+ 14 - 2
src/StatsBundle/Resources/translations/StatsBundle.es.yml

@@ -230,6 +230,15 @@ list:
     label_last_flap_time: Last Flap Time
     label_flap_row_status: Flap Row Status
     label_create_time: Create Time
+    label_cablemodem: Cablemodem
+    label_node: Nodo
+    label_cmts_state: Estado en CMTS
+    label_cmts_index: Indice en CMTS
+    label_sla_numbers: SLA Números
+    label_latency: Latency
+    label_jitter: Jitter
+
+
     
 help:
     url: Url a consultar dispositivos
@@ -248,10 +257,13 @@ ONU: ONU
 Mapa ONUs: Mapa ONUs
 link_action_show_onu_in_map: Ver en Mapa
 link_action_show_onu_in_ftth: Ver configuración en FTTH
+link_action_add_onu_in_ftth: Agregar al sistema
+link_action_show_cablemodem_in_map: Ver en Mapa
+link_action_show_cablemodem_in_cablemodem: Ver configuración en Cablemodem
+link_action_add_cablemodem_in_cablemodem: Agregar al sistema
 link_action_update_devices: Actualizar dispositivos
 link_action_show_ponport_in_map: Ver en Mapa
 show_ponport: Mostrar PonPort
-link_action_add_onu_in_ftth: Agregar al sistema
 msg_no_registered_in_ftth: La ONU no se encuentra registrada en FTTH. Puede agregarla desde Acciones > Agregar al sistema.
 msg_no_exist_map: No se encuentra el mapa solicitado.
 action_olt_show_report: Informe
@@ -293,6 +305,6 @@ consumption_info_evolution: Evolución del consumo mensual y porcentaje de utili
 nas_data_origen: Salvo OLT Huawei, estos valores se obtienen desde el NAS, consultar sobre la ejecución de los comandos de estadísticas sobre el mismo.
 picker_find: Buscar
 rx_tx_title: Niveles de Rx / Tx
-cablemodems_with_lat_lng: cablemodems ceolocalizados
+cablemodems_with_lat_lng: cablemodems geolocalizados
 interface_cms_map_title: RX de cablemodems en la Interface
 consumption_subtitle: Consumo mensual acumulado

+ 11 - 0
src/StatsBundle/Resources/views/Cablemodem/base_show_v2.html.twig

@@ -0,0 +1,11 @@
+{% extends 'SonataAdminBundle:CRUD:base_show.html.twig' %}
+
+{% block show %}
+    <link rel="stylesheet" type="text/css" href="{{ asset('bundles/stats/css/style.css') }}">
+    {% include 'LeafletBundle:Leaflet:resources_only_leaflet.html.twig' %}
+    <script src="{{ asset('bundles/stats/highcharts/code/highcharts.js') }}" type="text/javascript" charset="utf-8"></script>
+    <script src="{{ asset('bundles/stats/highcharts/highchartsConfig.js') }}" type="text/javascript" charset="utf-8"></script>
+
+    {{ render(controller('StatsBundle:Stats:showCm', { 'object': object ,'from':admin.parameters.from, 'to':admin.parameters.to})) }}
+    
+{% endblock %}

+ 153 - 0
src/StatsBundle/Resources/views/Stats/Template/cablemodem_info_1.html.twig

@@ -0,0 +1,153 @@
+<div class="box box-widget">
+    <div class="box-body">
+        <table class="table table-hover table-condensed table-striped table-bordered">
+        <thead><th colspan=2>{{ 'list.label_cablemodem'|trans({}, 'StatsBundle') }}</th></thead>
+        <tbody>
+            <tr>
+                <td style="white-space: nowrap;">{{ 'list.label_mac'|trans({}, 'StatsBundle') }}</td>
+                <td>
+                    {{ cablemodem.getMac|upper }}
+                </td>
+            </tr>
+            
+            <tr>
+                <td style="white-space: nowrap;">{{ 'list.label_ip'|trans({}, 'StatsBundle') }}</td>
+                <td>
+                    {% if cablemodem.getIp is not null %}
+                        {{cablemodem.getIp}}
+                    {% else %}
+                        <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                </td>
+            </tr>
+
+            <tr>
+                <td style="white-space: nowrap;">{{ 'list.label_up_if'|trans({}, 'StatsBundle') }}</td>
+                <td>
+                {% if cablemodem.getUpIf is not null %}
+                    {{cablemodem.getUpIf}}
+                {% else %}
+                    <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                {% endif %}
+                </td>
+            </tr>
+            
+            <tr>
+                <td style="white-space: nowrap;">{{ 'list.label_down_if'|trans({}, 'StatsBundle') }}</td>
+                <td>
+                {% if cablemodem.getDownIf is not null %}
+                    {{cablemodem.getDownIf}}
+                {% else %}
+                    <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                {% endif %}
+                </td>
+            </tr>
+            <tr>
+                <td style="white-space: nowrap;">{{ 'list.label_created'|trans({}, 'StatsBundle') }}</td>
+                <td>
+                {% if remoteData['cm_created'] is not null %}
+                    {{remoteData['cm_created']}}
+                {% else %}
+                    <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                {% endif %}
+                </td>
+            </tr>
+            <tr>
+                <td style="white-space: nowrap;">{{ 'list.label_operative_state'|trans({}, 'StatsBundle') }}</td>
+                <td>
+                {% if remoteData['cm_currentState'] is not null %}
+                    {{remoteData['cm_currentState']}}
+                {% else %}
+                    <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                {% endif %}
+                </td>
+            </tr>
+            {% if urlCm is not null %}
+            <tr>
+                {% if remoteData['device_id'] is not null %}
+                    {% set url = urlCm ~ "/admin/cablemodem/cablemodem/" ~ remoteData['device_id'] ~ "/show" %}
+                    <td colspan=2 style="white-space: nowrap; padding: 0">
+                        <a target="_blank" class="sonata-action-element" href="{{url}}">
+                        <div style="width: 100%; background-color: white; text-align: center; border: 1px solid #3c8dbc; padding: 5px 0px">
+                            <i class="fa fa-cog" aria-hidden="true"></i>  {{ 'link_action_show_cablemodem_in_cablemodem'|trans({}, 'StatsBundle') }}
+                        </div>
+                        </a>
+                    </td>    
+                {% else %}
+                    {% set url = urlCm ~ "/admin/cablemodem/cablemodem/create" %}
+                    <td colspan=2 style="white-space: nowrap; padding: 0">
+                        <a target="_blank" class="sonata-action-element" href="{{url}}">
+                        <div style="width: 100%; background-color: white; border: 1px solid #eb7f7f; text-align: center; padding: 5px 0px">
+                            <i class="fa fa-plus-circle" aria-hidden="true"></i>  {{ 'link_action_add_cablemodem_in_cablemodem'|trans({}, 'StatsBundle') }}
+                        </div>
+                        </a>
+                    </td>
+                {% endif %}
+            </tr>
+            {% else %}
+            <tr>
+                <td colspan=2 style="white-space: nowrap; padding: 0">
+                    <a target="_blank" class="sonata-action-element a-reload" href="#">
+                    <div style="width: 100%; background-color: white; text-align: center; border: 1px solid #3c8dbc; padding: 5px 0px">
+                        <i class="fa fa-refresh" aria-hidden="true"></i>  {{ 'link_action_reload_show_stats'|trans({}, 'StatsBundle') }}
+                    </div>
+                    </a>
+                </td>
+            </tr>    
+            {% endif %}
+        </table>
+        <br />
+        <table class="table table-hover table-condensed table-striped table-bordered">
+            <thead><th colspan=2>{{ 'list.label_client'|trans({}, 'StatsBundle') }}</th></thead>    
+            <tbody>
+                <tr>
+                    <td style="white-space: nowrap;">{{ 'list.label_client_externalId'|trans({}, 'StatsBundle') }}</td>
+                    <td>
+                    {% if remoteData['client_externalId'] is not null %}
+                        {{remoteData['client_externalId']}}
+                    {% else %}
+                        <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                </tr>
+                <tr>
+                    <td>{{ 'list.label_client_name'|trans({}, 'StatsBundle') }}</td>
+                    <td>
+                    {% if remoteData['client_name'] is not null %}
+                        {{remoteData['client_name']}}
+                    {% else %}
+                        <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                </tr>
+                <tr>
+                    <td>{{ 'list.label_client_address'|trans({}, 'StatsBundle') }}</td>
+                    <td>
+                    {% if remoteData['client_address'] is not null %}
+                        {{remoteData['client_address']}}
+                    {% else %}
+                        <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                </tr>
+                <tr>
+                    <td style="white-space: nowrap;">{{ 'list.label_operative_state'|trans({}, 'StatsBundle') }}</td>
+                    <td>
+                    {% if remoteData['client_currentState'] is not null %}
+                        {{remoteData['client_currentState']}}
+                    {% else %}
+                        <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                </tr>
+                
+            </tbody>
+        </table>
+    </div>
+</div>
+
+<script type="text/javascript">
+$('.a-reload').click( function(e) {e.preventDefault(); location.reload(); return false; }); 
+</script>
+
+{# {{dump(remoteData)}} #}

+ 130 - 0
src/StatsBundle/Resources/views/Stats/Template/cablemodem_info_2.html.twig

@@ -0,0 +1,130 @@
+<div class="box box-widget">
+    <div class="box-body">
+        <table class="table table-hover table-condensed table-striped table-bordered">
+        <thead><th colspan=2>{{ 'list.label_cmts'|trans({}, 'StatsBundle') }}</th></thead>
+        <tbody>
+            <tr>
+                <td style="white-space: nowrap;">{{ 'list.label_name'|trans({}, 'StatsBundle') }}</td>
+                <td>
+                {% if remoteData['cmts_name'] is not null %}
+                    {{remoteData['cmts_name']}}
+                {% else %}
+                    <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                {% endif %}
+                </td>
+            </tr>
+            <tr>
+                <td style="white-space: nowrap;">{{ 'list.label_ip'|trans({}, 'StatsBundle') }}</td>
+                <td>
+                {% if remoteData['cmts_ip'] is not null %}
+                    {{remoteData['cmts_ip']}}
+                {% else %}
+                    <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                {% endif %}
+                </td>
+            </tr>
+            <tr>
+                <td style="white-space: nowrap;">{{ 'list.label_node'|trans({}, 'StatsBundle') }}</td>
+                <td>
+                {% if remoteData['node_name'] is not null %}
+                    {{remoteData['node_name']}}
+                {% else %}
+                    <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                {% endif %}
+                </td>
+            </tr>
+        </table>
+        <br />
+        <table class="table table-hover table-condensed table-striped table-bordered">
+            <thead><th colspan=2>{{ 'list.label_configuration'|trans({}, 'StatsBundle') }}</th></thead>    
+            <tbody>
+                <tr>
+                    <td>{{ 'list.label_profile'|trans({}, 'StatsBundle') }}</td>
+                    <td>
+                    {% if remoteData['profile_name'] is not null %}
+                        {{remoteData['profile_name']}}<span class="no_defined">&nbsp;&nbsp;&nbsp;(limit: {{remoteData['profile_consumption']}} <span class="text_column_stats">GB</span>)<span>
+                    {% else %}
+                        <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                </tr>
+                <tr>
+                    <td>{{ 'list.label_profile_download'|trans({}, 'StatsBundle') }} <span class="in-label">(in)</span></td>
+                    <td>
+                    {% if remoteData['profile_download'] is not null %}
+                        {{remoteData['profile_download']}} <span class="text_column_stats">bits/s</span>
+                    {% else %}
+                        <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                </tr>
+                <tr>
+                    <td>{{ 'list.label_profile_upload'|trans({}, 'StatsBundle') }} <span class="out-label">(out)</span></td>
+                    <td>
+                    {% if remoteData['profile_upload'] is not null %}
+                        {{remoteData['profile_upload']}} <span class="text_column_stats">bits/s</span>
+                    {% else %}
+                        <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                </tr>
+                <tr>
+                    <td style="white-space: nowrap;">{{ 'list.label_cmts_state'|trans({}, 'StatsBundle') }}</td>
+                    <td>{% include 'StatsBundle:Templates:macro_status.html.twig' with {'value': cablemodem.getStatus} only %}</td>
+                </tr>
+                <tr>
+                    <td style="white-space: nowrap;">{{ 'list.label_cmts_index'|trans({}, 'StatsBundle') }}</td>
+                    <td>
+                    {% if cablemodem.getIndex is not null %}
+                        {{cablemodem.getIndex}}
+                    {% else %}
+                        <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                </tr>
+                <tr>
+                    <td style="white-space: nowrap;">{{ 'list.label_updated'|trans({}, 'StatsBundle') }}</td>
+                    <td>
+                    {% if cablemodem.getUpdated is not null %}
+                        {{cablemodem.getUpdated|date('Y-m-d H:i:s')}}
+                    {% else %}
+                        <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                </tr>
+                <tr>
+                    <td>
+                    {% if cablemodem.getTxPower is not null %}
+                        TX {% include 'StatsBundle:Templates:cm_field_tx.html.twig' with {'value': cablemodem.getTxPower} only %}
+                    {% else %}
+                        TX <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                    <td>
+                    {% if cablemodem.getRxPower is not null %}
+                        RX {% include 'StatsBundle:Templates:cm_field_rx.html.twig' with {'value': cablemodem.getRxPower} only %}
+                    {% else %}
+                        RX <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                </tr>
+                {# <tr>
+                    <td>
+                    {% if onu.getVoltage is not null %}
+                        Voltage {{ onu.getVoltage|number_format(2, '.', ',')}} <span class="text_column_stats">V</span>
+                    {% else %}
+                        Voltage <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                    <td>
+                    {% if onu.getTemperature is not null %}
+                        Temperature {{ onu.getTemperature|number_format(2, '.', ',')}} <span class="text_column_stats">ºC</span>
+                    {% else %}
+                        Temperature <span class="no_defined">{{ 'no_defined'|trans({}, 'StatsBundle') }}</span>
+                    {% endif %}
+                    </td>
+                </tr> #}
+            </tbody>
+        </table>
+    </div>
+</div>

+ 84 - 0
src/StatsBundle/Resources/views/Stats/Template/cablemodem_latency_jitter_info.html.twig

@@ -0,0 +1,84 @@
+<table class="table table-condensed table-bordered" style="margin-top:57px; border-top:2px solid #3c8dbc;">
+<thead>
+    <th>
+    {# <i class="fa fa-line-chart" aria-hidden="true"></i> #}
+    {{ 'list.label_sla_numbers'|trans({}, 'StatsBundle') }}
+    </th>
+</thead>
+<tbody>
+    {% if series['latency']['count'] > 0 %}
+    <tr>
+        <td>
+            <span style="color:#7cb5ec">{{ 'list.label_latency'|trans({}, 'StatsBundle') }} </span>
+            <br />
+            <div class="clearfix">
+                <div class="clearfix" style="float:left">
+                    <div style="float:left">
+                    <span style="font-weight: bold; font-size: 50px">
+                        {{series['latency']['avg']|number_format(2,'.','')}}
+                    </span>
+                    </div>
+                    <div style="float:left; padding-top:20px; padding-left: 5px">
+                        avg 
+                        <br />
+                        <span class="text_column_stats">ms</span>
+                    </div>
+                </div>
+                <div class="clearfix"  style="float:left">
+                    <span style="font-weight: bold; font-size: 50px; color:#7cb5ec">/</span>
+                </div>
+                <div class="clearfix"  style="float:left">
+                    <div style="float:left">
+                    <span style="font-weight: bold; font-size: 50px">
+                        {{series['latency']['max']|number_format(2,'.','')}}
+                    </span>
+                    </div>
+                    <div style="float:left; padding-top:20px; padding-left: 5px">
+                        max 
+                        <br />
+                        <span class="text_column_stats">ms</span>
+                    </div>
+                </div>
+            </div>
+        </td>
+    </tr>
+    {% endif %}
+    
+    {% if series['jitter']['count'] > 0 %}
+    <tr>
+        <td>
+            <span style="color:#f7a35c">{{ 'list.label_jitter'|trans({}, 'StatsBundle') }} </span>
+            <br />
+            <div class="clearfix">
+                <div class="clearfix" style="float:left">
+                    <div style="float:left">
+                    <span style="font-weight: bold; font-size: 50px">
+                        {{series['jitter']['avg']|number_format(2,'.','')}}
+                    </span>
+                    </div>
+                    <div style="float:left; padding-top:20px; padding-left: 5px">
+                        avg 
+                        <br />
+                        <span class="text_column_stats">ms</span>
+                    </div>
+                </div>
+                <div class="clearfix"  style="float:left">
+                    <span style="font-weight: bold; font-size: 50px; color:#f7a35c">/</span>
+                </div>
+                <div class="clearfix"  style="float:left">
+                    <div style="float:left">
+                    <span style="font-weight: bold; font-size: 50px">
+                        {{series['jitter']['max']|number_format(2,'.','')}}
+                    </span>
+                    </div>
+                    <div style="float:left; padding-top:20px; padding-left: 5px">
+                        max 
+                        <br />
+                        <span class="text_column_stats">ms</span>
+                    </div>
+                </div>
+            </div>
+        </td>
+    </tr>
+    {% endif %}
+</table>

+ 41 - 0
src/StatsBundle/Resources/views/Stats/Template/cablemodem_location.html.twig

@@ -0,0 +1,41 @@
+<div style="padding: 10px">
+    <div id="map"></div>
+    {% if remoteData['device_id'] is not null and urlCm is not null %}
+    {% set url = urlCm ~ "/admin/cablemodem/cablemodem/" ~ remoteData['device_id'] ~ "/edit" %}
+    <a target="_blank" class="sonata-action-element" href="{{url}}">
+    <div style="width: 100%; background-color: white; text-align: center; border: 1px solid #3c8dbc; padding: 5px 0px">
+        <i class="fa fa-map-marker" aria-hidden="true"></i>  {{ 'link_action_edit_location'|trans({}, 'StatsBundle') }}
+    </div>
+    </a>
+    {% endif %}
+</div>
+{% include '@Stats/Stats/picker.html.twig' %}
+<script>
+
+/* --------------------- PROGRAMA PRINCIPAL ------------------------- */
+initializeMap();
+/* ------------------- FIN PROGRAMA PRINCIPAL ----------------------- */
+
+/* --------------------- Carga Mapa -------------------------------- */
+
+function initializeMap() {
+
+    window.map = new L.Map('map', { center: new L.LatLng({{location['lat']}}, {{location['lng']}}), zoom: {{location['zoom']}} });
+
+    var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
+    var osmAttrib = '&copy; OpenStreetMap';
+    var osm = L.tileLayer(osmUrl, { maxZoom: 18, attribution: osmAttrib });
+
+    var controlLayers = L.control.layers({
+        'OSM': osm.addTo(window.map),
+        "Google": L.tileLayer('http://www.google.cn/maps/vt?lyrs=s@189&gl=cn&x={x}&y={y}&z={z}', {zIndex:1, attribution: '&copy; Google'})
+    }, {}, { position: 'topleft', collapsed: false });
+
+    {% if location['marker'] %}
+        var marker = L.marker([{{location['lat']}}, {{location['lng']}}]).addTo(map);
+    {% endif %}
+    
+
+}
+
+</script>

+ 393 - 0
src/StatsBundle/Resources/views/Stats/show_cm.html.twig

@@ -0,0 +1,393 @@
+<div class="box box-primary">
+    <br />
+    <div class="box-body">
+        <div class="col-sm-12">
+            <div class="nav-tabs-custom">
+                <ul class="nav nav-tabs">
+                    <li class="active">
+                        <a href="#tab_1" data-toggle="tab">{{ 'Description'|trans({}, 'StatsBundle') }}</a>
+                    </li>
+                    <li>
+                        <a href="#tab_2" data-toggle="tab">{{ 'Radio Frequency'|trans({}, 'StatsBundle') }} <span class="no_defined nas_data_origen">(TX avg {{series['tx_2']['avg']|number_format(2)}} / RX avg {{series['rx_3']['avg']|number_format(2)}})</span></a>
+                    </li>
+                    <li>
+                        <a href="#tab_3" data-toggle="tab">{{ 'Codewords'|trans({}, 'StatsBundle') }} <span class="no_defined nas_data_origen"></span></a>
+                    </li>
+                    <li>
+                        <a href="#tab_4" data-toggle="tab">{{ 'SLA'|trans({}, 'StatsBundle') }} <span class="no_defined nas_data_origen"></span></a>
+                    </li>
+                </ul>
+                <div class="tab-content clearfix">
+                    
+                    {# TAB Description #}
+                    <div class="tab-pane active" id="tab_1">
+                        <div class="clearfix">
+                            <div class="col-sm-3">
+                                {% include '@Stats/Stats/Template/cablemodem_info_1.html.twig' %}
+                            </div>
+                            <div class="col-sm-4">
+                                {% include '@Stats/Stats/Template/cablemodem_info_2.html.twig' %}
+                            </div>
+                            <div class="col-sm-5">
+                                {% include '@Stats/Stats/Template/cablemodem_location.html.twig' %}
+                            </div>
+                        </div>
+                        <br />
+                        <div class="clearfix">
+                            <div class="col-sm-9" style="text-align:center">
+                                <div id="cablemodem_bandwidth" style="height: 400px;"></div>
+                            </div>
+                            <div class="col-sm-3">
+                                {% include '@Stats/Stats/Template/onu_bandwidth_info.html.twig' %}
+                            </div>
+                        </div>
+                        <br />
+                        
+                        <div>
+                            <div class="col-sm-9" style="text-align:center">
+                                <div id="cablemodem_consumption" style="height: 400px;"></div>
+                            </div>
+                            <div class="col-sm-3">
+                                {% include '@Stats/Stats/Template/onu_consumption_info.html.twig' %}
+                            </div>
+                        </div>
+                        <br />
+
+                        <div class="clearfix">
+                            <div class="col-sm-12" style="text-align:center">
+                                <div id="cablemodem_status" style="height: 400px;"></div>
+                            </div>
+                        </div>
+                    </div>
+
+                    {# TAB Frecuency #}                    
+                    <div class="tab-pane" id="tab_2">
+                        <div class="clearfix">
+                            <div class="col-sm-12" style="text-align:center">
+                                <div id="cablemodem_tx" style="height: 400px;"></div>
+                            </div>
+                            <div class="col-sm-12" style="text-align:center">
+                                <div id="cablemodem_rx" style="height: 400px;"></div>
+                            </div>
+                            <div class="col-sm-12" style="text-align:center">
+                                <div id="cablemodem_signal" style="height: 400px;"></div>
+                            </div>
+                            <div class="col-sm-12" style="text-align:center">
+                                <div id="cablemodem_mx" style="height: 400px;"></div>
+                            </div>
+                        </div>
+                    </div>
+                    
+                    {# TAB Codewords #}                    
+                    <div class="tab-pane" id="tab_3">
+                        <div class="clearfix">
+                            {% for index in portsMetrics['correcteds'] %}
+                            <div class="col-sm-12"  style="width: 100%">
+                                <div id="cablemodem_codewords_{{index}}" style="width: 100%"></div>
+                            </div>
+                            {% endfor %}
+                        </div>
+                    </div>
+                    
+                    {# TAB SLA #}
+                    <div class="tab-pane" id="tab_4">
+                        <div class="clearfix">
+                            
+                            <div class="col-sm-9" >
+                                <div id="cablemodem_latency_jitter" style="width: 100%"></div>
+                            </div>
+                            <div class="col-sm-3">
+                                {% include '@Stats/Stats/Template/cablemodem_latency_jitter_info.html.twig' %}
+                            </div>
+                            
+                        </div>
+
+                        <div class="clearfix">
+                            <div class="col-sm-12" >
+                                <div id="cablemodem_loss" style="width: 100%"></div>
+                            </div>
+                        </div>
+                    </div>
+                   
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script type="text/javascript">
+
+var from = {{from}};
+var to = {{to}};
+var markerEnable = false;
+if((to - from) <= 21600) {
+    markerEnable = true;
+}
+
+
+Highcharts.chart('cablemodem_bandwidth', {
+    chart: {type: 'spline'},
+    title: {text: '{{'Bandwidth Cablemodem'|trans({}, 'StatsBundle')}}'},
+    subtitle: {text: 'IN Bandwidth / OUT Bandwidth'},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: {labels: {formatter: bandwidthAxisLabel,align: 'left'},min: 0},
+    tooltip: {formatter: bandwidthTooltip},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, spline: {marker: {enabled: true}}},
+    series: [{
+        name: "IN Bandwidth",
+        data: {{series['in_bandwidth']['data']|json_encode}},
+        color: '#3f6833'
+        },{
+        name: "OUT Bandwidth",
+        data: {{series['out_bandwidth']['data']|json_encode}},
+        color: '#e24d42'
+    }]
+});
+
+Highcharts.chart('cablemodem_consumption', {
+    chart: {type: 'area'},
+    title: {text: '{{'Consumption Cablemodem'|trans({}, 'StatsBundle')}}'},
+    subtitle: {text: 'IN Consumption / OUT Consumption'},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: {labels: {formatter: consumptionAxisLabel,align: 'left'},min: 0},
+    tooltip: {formatter: consumptionTooltip},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, spline: {marker: {enabled: true}}},
+    series: [{
+        name: "IN Consumption",
+        data: {{series['in_consumption']['data']|json_encode}},
+        color: '#3f6833'
+        },{
+        name: "OUT Consumption",
+        data: {{series['out_consumption']['data']|json_encode}},
+        color: '#e24d42'
+    }]
+});
+
+Highcharts.chart('cablemodem_status', {
+    chart: {type: 'area'},
+    title: {text: '{{'Status'|trans({}, 'StatsBundle')}}'},
+    subtitle: {text: 'Online / Offline'},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: { categories: ['Offline', 'Online'], min: 0,stackLabels: {enabled: true,style: {fontWeight: 'bold',color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'}}},
+    tooltip: {formatter: onuStatusTooltip},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, column: {stacking: 'normal',dataLabels: {enabled: true,color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'}}},
+    legend: {enabled: false},
+    series: [{
+        name: 'Status',
+        step: 'right',
+        data: {{series['status']['data']|json_encode}},
+        color: '#3f6833'
+    }]
+});
+
+Highcharts.chart('cablemodem_latency_jitter', {
+    chart: {type: 'spline'},
+    title: {text: '{{''|trans({}, 'StatsBundle')}}'},
+    subtitle: {text: 'Latency / Jitter'},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: {labels: {align: 'left'}},
+    tooltip: {valueSuffix: ' ms',valueDecimals: 2},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, spline: {marker: {enabled: true}}},
+    series: [{
+        name: "Latency",
+        data: {{series['latency']['data']|json_encode}}
+        },{
+        name: "Jitter",
+        data: {{series['jitter']['data']|json_encode}}
+    }]
+});
+
+Highcharts.chart('cablemodem_loss', {
+    chart: {type: 'area'},
+    title: {text: '{{ ''|trans({}, 'StatsBundle') }}'},
+    subtitle: {text: 'Packet Loss'},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: {labels: {format: '{value} %'}, min: 0},
+    tooltip: {valueSuffix: ' %',valueDecimals: 2},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, spline: {marker: {enabled: true}}},
+    legend: {enabled: false},
+    series: [{
+        name: "Packet Loss",
+        data: {{series['loss']['data']|json_encode}},
+        color: '#1299da',
+        fillOpacity: 0.2
+    }]
+});
+
+{% for index in portsMetrics['correcteds'] %}
+Highcharts.chart('cablemodem_codewords_{{index}}', {
+    chart: {type: 'spline'},
+    title: {text: 'Port {{index}}'},
+    subtitle: {text: 'Codewords'},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: {labels: {format: '{value}'},min: 0},
+    tooltip: {valueSuffix: ' codewords',valueDecimals: 0},
+    plotOptions: {series: {marker: {enabled: markerEnable}, dataLabels: {enabled: false, color: '#666666'}}},
+    series: [
+        {
+        name: "Correcteds",
+        data: {{series['correcteds_'~index]['data']|json_encode}},
+        },
+        {
+        name: "Unerroreds",
+        data: {{series['unerroreds_'~index]['data']|json_encode}},
+        },
+        {
+        name: "Uncorrectables",
+        data: {{series['uncorrectables_'~index]['data']|json_encode}},
+        }
+    ]
+});
+{% endfor %}
+
+
+Highcharts.chart('cablemodem_tx', {
+    chart: {type: 'spline'},
+    title: {text: '{{'TX Power'|trans({}, 'StatsBundle')}}'},
+    subtitle: {},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: {labels: {align: 'left'}},
+    tooltip: {valueSuffix: ' dBmV',valueDecimals: 2},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, spline: {marker: {enabled: false}}},
+    series: [
+        {% for index in portsMetrics['txPower'] %}
+        {
+            name: "Port {{index}}",
+            data: {{series['tx_' ~ index]['data']|json_encode}}
+        },
+        {% endfor %}
+    ]
+});
+
+Highcharts.chart('cablemodem_rx', {
+    chart: {type: 'spline'},
+    title: {text: '{{'RX Power'|trans({}, 'StatsBundle')}}'},
+    subtitle: {},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: {labels: {align: 'left'}},
+    tooltip: {valueSuffix: ' dBmV',valueDecimals: 2},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, spline: {marker: {enabled: false}}},
+    series: [
+        {% for index in portsMetrics['rxPower'] %}
+        {
+            name: "Port {{index}}",
+            data: {{series['rx_' ~ index]['data']|json_encode}}
+        },
+        {% endfor %}
+    ]
+});
+
+Highcharts.chart('cablemodem_signal', {
+    chart: {type: 'spline'},
+    title: {text: '{{'SNR'|trans({}, 'StatsBundle')}}'},
+    subtitle: {},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: {labels: {align: 'left'}},
+    tooltip: {valueSuffix: ' dB',valueDecimals: 2},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, spline: {marker: {enabled: false}}},
+    series: [
+        {% for index in portsMetrics['signal'] %}
+        {
+            name: "Port {{index}}",
+            data: {{series['signal_' ~ index]['data']|json_encode}}
+        },
+        {% endfor %}
+    ]
+});
+
+Highcharts.chart('cablemodem_mx', {
+    chart: {type: 'spline'},
+    title: {text: '{{'Microreflection'|trans({}, 'StatsBundle')}}'},
+    subtitle: {},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: {labels: {align: 'left'}},
+    tooltip: {valueSuffix: ' dBc',valueDecimals: 2},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, spline: {marker: {enabled: false}}},
+    series: [
+        {% for index in portsMetrics['microreflection'] %}
+        {
+            name: "Port {{index}}",
+            data: {{series['microreflection_' ~ index]['data']|json_encode}}
+        },
+        {% endfor %}
+    ]
+});
+
+
+{#
+/*
+Highcharts.chart('onu_rf', {
+    chart: {type: 'area'},
+    title: {text: '{{ 'rx_tx_title'|trans({}, 'StatsBundle') }}'},
+    subtitle: {},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: {labels: {format: '{value} dB'},min: null},
+    tooltip: {valueSuffix: ' dB',valueDecimals: 2},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, spline: {marker: {enabled: true}}},
+    series: [{
+        name: "TX Power",
+        data: {{series['tx']['data']|json_encode}},
+        color: '#6ed0e0',
+        fillOpacity: 0.2
+    },{
+        name: "RX Power",
+        data: {{series['rx']['data']|json_encode}},
+        color: '#4841AD',
+        fillOpacity: 0.2
+    }]
+});
+
+Highcharts.chart('onu_voltage', {
+    chart: {type: 'area'},
+    title: {text: 'Voltage'},
+    subtitle: {},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: {labels: {format: '{value} V'},min: 0},
+    tooltip: {valueSuffix: ' V',valueDecimals: 2},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, spline: {marker: {enabled: true}}},
+    legend: {enabled: false},
+    series: [{
+        name: "Voltage",
+        data: {{series['voltage']['data']|json_encode}},
+        color: '#4841AD',
+        fillOpacity: 0.2
+    }]
+});
+
+Highcharts.chart('onu_temperature', {
+    chart: {type: 'area'},
+    title: {text: 'Temperature'},
+    subtitle: {},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: {labels: {format: '{value} ºC'},min: 0},
+    tooltip: {valueSuffix: ' ºC',valueDecimals: 2},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, spline: {marker: {enabled: true}}},
+    legend: {enabled: false},
+    series: [{
+        name: "Temperature",
+        data: {{series['temperature']['data']|json_encode}},
+        color: '#B75426',
+        fillOpacity: 0.2
+    }]
+});
+
+Highcharts.chart('onu_status', {
+    chart: {type: 'area'},
+    title: {text: 'Estatus'},
+    subtitle: {text: 'Online / Offline'},
+    xAxis: {type: 'datetime',dateTimeLabelFormats: {month: '%e. %b',year: '%b'},title: {text: 'Date'}},
+    yAxis: { categories: ['Offline', 'Online'], min: 0,stackLabels: {enabled: true,style: {fontWeight: 'bold',color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'}}},
+    tooltip: {formatter: onuStatusTooltip},
+    plotOptions: {series: {marker: {enabled: markerEnable}}, column: {stacking: 'normal',dataLabels: {enabled: true,color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'}}},
+    legend: {enabled: false},
+    series: [{
+        name: 'Status',
+        step: 'right',
+        data: {{series['status']['data']|json_encode}},
+        color: '#3f6833'
+    }]
+});
+*/
+#}
+
+</script>