Automatisierte Builds in Azure DevOps/VSTS

Ein essentieller Teil einer erfolgreichen Softwareenwicklung in einem Unternehmen ist Continuous Integration, ein ständig verfügbarer kontinuierlicher Build. Und daneben gehört natürlich Continuus Deployment hinein. So werden fertige Builds auch gleich auf Herz und Nieren geprüft.

In diesem Artikel geht es darum, wie man aus einem .Net 4.7-Projekt mit mehreren Setups und exe-Dateien (GUI und CUI) einen continuus Build hinbekommt. Dabei sollen die Versionsnummern immer stetig hochgezählt werden und sowohl in jeder Assembly als auch in jedem Setup landen. Zusätzlich gibt es einige GUI-Komponenten, die das unsägliche .Net-licensing verwenden. Auch dafür gibt es eine Lösung.

Der Build wird eingerichtet auf Azure DevOps. Modernere Versionen sollten Ähnlich oder einfacher einzurichten sein.

Ziel

Folgende Probleme sollen adressiert und gelöst werden:

  • .Net Licensing von GUI-Komponenten (z.b. PerpetuumSoft)
  • Versionsnummern automatisch vergeben
  • Basis der Versionsnummer konfigurierbar (beim Build)
  • Versionsnummer in jeder Assembly (Asm. Ver + File Ver.)
  • Versionsnummer in jedem MSI, „Drüberinstallieren“ soll gehen.

Lizensierung

Mit .Net Licensing hat Microsoft ehemals ein Standardverfahren etabliert, mit dem Komponenten (v.a. Windows Forms) lizensiert werden können. Aufgrund des Alters und seiner Art, ein eher unsägliches Ding. Aber man kommt damit klar.

Die primäre Idee von .Net Licensing ist es, für GUI-Komponenten Entwicklerlizenzen während der Entwicklung durchzusetzen. Das sieht dann etwa so aus: Der Entwickler bindet eine GUI-Komponente ein und bei jeder Verwendung prüft diese, ob auf dem Entwicklerrechner eine Lizenz vorhanden ist. Ist das nicht der Fall, kann etwa ein Nag-Screen aufpoppen. Dazu gehört noch der Lizenzcompiler LC.Exe, der aus *.licx-Dateien *.licenses-Dateien baut. Das erledigt jeweils die Komponente, die auf ihre Weise checkt, ob sie auf diesem Entwicklersystem lizenziert ist. Deshalb steht auch in der *.licx-Datei eine Liste von Komponenten, die der LC.EXE aufrufen soll (per Reflection). Im Ergebnis entsteht eine *.licenses-Datei, die als Eingebettete Ressource in die Assembly eincompiliert wird. Danach ist die Komponente dauerhaft auch auf Kundensystemen lizensiert.

Das Problem ist nun: So lange alles nur auf Entwicklermaschinen lief, ging alles gut. Der CI-Build läuft aber auf einer frisch instantiierten VM in der Cloud und diese hat keine Entwicklerlizenz installiert. Ergo kann es passieren, dass ein Nag-Screen aufgeht und keiner ihn kann klicken. Der Build wird nie fertig.

Info dazu auf Stackoverflow

Lösung: Man macht einmal einen ordentlichen Build auf einem Entwicklersystem und sammelt dort die *.licenses-Dateien ein (Bin-VZ). Dann setzt man den Dateityp in der SLN von *.licx auf „None„. Sodann checkt man die *.licenses Dateien pro Assembly ein und bindet sie als „Embedded Resource“ zusätzlich in die SLN ein.

Ab da läuft der Build ohne Nag-Screen durch. Nur beim Aktualisieren der Komponenten muss man diesen Vorgang wiederholen. Man macht somit LC.EXE arbeitslos und verhindert das Aufrufen des Lizensierungs-Codes.

Versionierung

Kommen wir zum Thema Versionsnummern. Die wichtigste Zutat für einen automatiserten Build sind korrekte und konfigurierbare Versionsnummern. Nur so kann man feststellen, ob ein Artefakt neuer oder älter ist und zu welchem Versionsstand er gehört. .Net bringt uns 3 verschiedene Versionsnummern, die je Assembly gesetzt werden können. Eine Erklärung dazu und zu „Semantischer Versionierung“ findet man hier:

Umsetzung

Um eine automatische Versionierung hinzubekommen braucht man zwei Zutaten:

  • Eine Pipeline-Variable für die Assemblyversion
  • Ein Skript, um die Versionsvariable zu verrechnen
  • Ein Build-Target für MSBUILD
Die Variable BuildVersionOfAssembly wird angelegt mit dem aktuellen Standardwert

Der Plan ist es, die Versionierung so zu machen, wie es in semantic versioning empfohlen wird. Also die verschiedenen Typen von Assembly-Versionsattributen korrekt zu setzen. Sprich: AssemblyVersion und AssemblyInformationalVersion ist die ‚fixe‘ Version. Darüber referenzieren und finden sich die abhängigen Assemblies. Die letzte Stelle ist leer. Derweil ist AssembyFileVersion quasi dieselbe Nummer aber mit gesetzter Build-Nummer, die irgendwie ausgerechnet wird.

Konkret kommt über die Build-Pipeline eine Variable AssemblyVersion hinein in Form einer 3-Stelligen Version. Z.B. „11.22.33“

Dies resultiert in:
AssemblyVersion = „11.22.33“
AssemblyInformationalVersion = „11.22.33“
AssembyFileVersion = „11.22.33.1928“
Das Versions-Rechen-Skript setzt die neue Variable BuildVersionOfAssembly auf den Wert „11.22.33.1928“ und exportiert sie als DevOps-Variable auf die Konsole. Die Möglichkeiten dabei sind grenzenlos. Üblicherweise sollte man die BuildID nutzen, welche eine stetig steigene Nummer je getriggerten Build im CI-System ist. Problem: Die Zahl wird irgendwann größer als die erlaubten 16-bit an dieser Stelle. Lösung: Man macht Modulo 2^16 und hofft, dass dies nur alle 65k Builds zu Problemen führt und inkrementiert dann schnell die Patch-Version (Stelle 3). Wahlweise kann man auch die oberen Bits auf Patch-Version geben; dann aber nur zwei Versionsstellen vorgeben. (alles hier nicht gemacht).

Skript

Version Script (PowerShell inline):

# This script computes the $(BuildVersionOfAssembly) variable off of the User set $(VersionOfAssembly) build var.
# adds the buid pipeline ID (ordered number) as the last figure of the version

# VersionOfAssembly is expected to be "x.y.z" BuildVersionOfAssembly becomes "x.y.z.buildID"
Write-Host  "Looking for VersionOfAssembly. Found : $Env:VersionOfAssembly"

if( -not ("$Env:VersionOfAssembly" -match "^\d+\.\d+\.\d+$" ))
{
   Write-Host  "##vso[task.LogIssue type=error;]Error: $Env:VersionOfAssembly does not match X.Y.Z format."
   exit 1
}

$BuildVersionOfAssembly = $Env:VersionOfAssembly + '.' + $Env:Build_BuildId
Write-Host  "BuildVersionOfAssembly= $BuildVersionOfAssembly"

#To set a variable in DevOps pipeline, use Write-Host
Write-Host "##vso[task.setvariable variable=BuildVersionOfAssembly]$BuildVersionOfAssembly"
Version Script in DevOps – Variablen Sektionen leer lassen

Version in Assemblies schreiben

Versionen sind als Varialben da, doch wie bekommen wir sie als Assembly-Attribute in die Assemblies hinein. MSBUILD hat das etwas unbekannte Merkmal ‚directory target‘. Dieses sind Kompile-Schritte, die MSBUILD pro Projekt durchführt. Setzt man sie richtig ein, werden diese Aufgaben für jedes Projekt im selben oder tieferen Verzeichnis ausgeführt. Siehe .

Das Skript muss also irgendwo ‚oben‘ im Projekt angelegt werden und wir nennen es ‚Directory.Build.targets‘. Innerhalb des Skripts kann sogar inline-C# verwendet werden. Dabei nutzen wir Reguläre Ausdrücke um die AssemblyInfo.cs-Dateien zu patchen (alle 3 Versionsattribute). Dabei wird aber nicht die eigentliche Datei gepatcht, sondern eine Kopie. Die Originale (im VCS eingecheckt) werden als ‚targets‘ ausgeschlossen und dafür die gepatchten hinzugefügt. Das ist besser als checkout+checkin auf Build- und Entwicklermaschinen. Denn diese Targets werden ja immer mit ausgeführt. Wenn aber BuildVersionOfAssembly leer ist, macht dieses ‚Target‘ nichts. Das Ganze sollte mit *.vb genauso funktionieren.

Script: \Directory.Build.targets

<Project DefaultTargets="Build" InitialTargets="UpdateAssemblyVersion" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- from:
    http://www.lionhack.com/2014/02/13/msbuild-override-assembly-version/
    Creates modified version of AssemblyInfo.cs, replaces
    [AssemblyVersion] attribute with the one specifying actual build version
    (from MSBuild properties), and includes that file instead of the
    original AssemblyInfo.cs in the compilation.

    Works with both, .cs and .vb version of the AssemblyInfo file, meaning
    it supports C# and VB.Net projects simultaneously.

    see:
    Global .NET Versioning Strategy – AssemblyInformationalVersion
    or https://intovsts.net/2015/08/24/tfs-build-2015-and-versioning/ for
    further information

    Note: C++ projects have a CommonCpp.targets
-->

  <Target Name="UpdateAssemblyVersion" BeforeTargets="Compile"
       Condition="'$(VersionOfAssembly)' != '' or '$(BuildVersionOfAssembly)' != ''">
    <!-- Find AssemblyInfo.cs or AssemblyInfo.vb in the "Compile"
        Items. Remove it from "Compile" Items because we will use a modified
        version instead. -->
    <ItemGroup>
      <OriginalAssemblyInfo Include="@(Compile)" Condition="%(Filename) == 'AssemblyInfo' And (%(Extension) == '.vb' Or %(Extension) == '.cs')" />
      <Compile Remove="**/AssemblyInfo.vb" />
      <Compile Remove="**/AssemblyInfo.cs" />
    </ItemGroup>
    <!--  Copy the original AssemblyInfo.cs/.vb to obj\ folder, i.e.
          $(IntermediateOutputPath). The copied filepath is saved into
          @(ModifiedAssemblyInfo) Item. -->
    <Copy SourceFiles="@(OriginalAssemblyInfo)"
          DestinationFiles="@(OriginalAssemblyInfo->'$(IntermediateOutputPath)%(Identity)_patched')">
      <Output TaskParameter="DestinationFiles" ItemName="ModifiedAssemblyInfo"/>
    </Copy>

    <!-- DON'T Use VersionAssembly if InfoVersionAssembly is empty -->
    <!-- <PropertyGroup> -->
    <!-- <InfoVersionAssembly Condition="'$(BuildVersionOfAssembly)'== ''">$(VersionOfAssembly)</InfoVersionAssembly> -->
    <!-- </PropertyGroup> -->

    <Message  Text="-------------------------------------------------------------------------------" Importance="high" />
    <Message Text="Setting AssemblyVersionAttribute to $(VersionOfAssembly) " Importance="high" />
    <Message Text="Setting AssemblyFileVersionAttribute to $(BuildVersionOfAssembly) " Importance="high" />
    <Message Text="Setting InfoVersionAssemblyAttribute to $(VersionOfAssembly) " Importance="high" />
    <Message Text="Temp file is %(ModifiedAssemblyInfo.FullPath) " Importance="high" />
    <Message Text="--------------------------------------------------------------------------------" Importance="high" />

    <!-- Replace the version bit (in AssemblyVersion and
        AssemblyFileVersion attributes) using regular expression. Use the
        defined property: $(VersionOfAssembly). -->

    <!-- TODO: For Relseases, AssemblyVersion should be set to InfoVersionAssembly -->
    <Message Text="Setting AssemblyVersion to $(VersionOfAssembly)" />
    <RegexUpdateFile Files="@(ModifiedAssemblyInfo)" 
                     Condition="'$(VersionOfAssembly)' != ''"
                     Regex="AssemblyVersion(Attribute)?\("(\d+)\.(\d+)\..*"\)"
                     ReplacementText="AssemblyVersion("$(VersionOfAssembly)")" 
                     />
    <Message Text="Setting AssemblyFileVersion to $(BuildVersionOfAssembly)" />
    <RegexUpdateFile Files="@(ModifiedAssemblyInfo)"
                     Condition="'$(VersionBuildVersionOfAssemblyOfAssembly)' != ''"
                     Regex="AssemblyFileVersion(Attribute)?\("(\d+)\.(\d+)\..*"\)"
                     ReplacementText="AssemblyFileVersion("$(BuildVersionOfAssembly)")"
                     />
    <Message Text="Setting InfoVersionAssembly to $(VersionOfAssembly)" />
    <RegexUpdateFile Files="@(ModifiedAssemblyInfo)"
                     Condition="'$(VersionOfAssembly)' != ''"
                     Regex="AssemblyInformationalVersion(Attribute)?\("(\d+)\.(\d+)\..*"\)"
                     ReplacementText="AssemblyInformationalVersion("$(VersionOfAssembly)")"
                     />
    <!-- Include the modified AssemblyInfo.cs/.vb file in "Compile" items (instead of the original). -->
    <ItemGroup>
      <Compile Include="@(ModifiedAssemblyInfo)" />
    </ItemGroup>
  </Target>

  <UsingTask TaskName="RegexUpdateFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
      <Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
      <Regex ParameterType="System.String" Required="true" />
      <ReplacementText ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Reference Include="System.Core" />
      <Using Namespace="System" />
      <Using Namespace="System.IO" />
      <Using Namespace="System.Text.RegularExpressions" />
      <Using Namespace="Microsoft.Build.Framework" />
      <Using Namespace="Microsoft.Build.Utilities" />
      <Code Type="Fragment" Language="cs">
        <![CDATA[
try {
var rx = new
System.Text.RegularExpressions.Regex(this.Regex);
for (int i = 0; i < Files.Length; ++i)
{
var path = Files[i].GetMetadata("FullPath");
if (!File.Exists(path)) continue;

var txt = File.ReadAllText(path);
txt = "// <auto-generated />\r\n" +
rx.Replace(txt, this.ReplacementText);
File.WriteAllText(path, txt);
}
return true;
}
catch (Exception ex) {
Log.LogErrorFromException(ex);
return false;
}
]]>
      </Code>
    </Task>
  </UsingTask>

  <!-- ConsoleToMsBuild="True" IgnoreStandardErrorWarningFormat="true" IgnoreExitCode="True" -->
  <!-- MsBuild is probably the only build tool in the world that can't copy dependencies without help.-->
  <!-- Therefore, I can't recommend msbuild for professional use. -->
  <!-- Add this lines to your project file:
  <PropertyGroup
  Condition="Exists('$(SolutionDir)CommonSettings.targets')">
  <BuildDependsOn>
  $(BuildDependsOn);
  CopyLocalAgain;
  </BuildDependsOn>
  </PropertyGroup>
  -->
  <Target Name="CopyLocalAgain">
    <!-- Bug with incremental clean should be fixed. -->
    <!-- <CreateItem Include="%(Reference.HintPath)" -->
    <!-- Condition="'%(Reference.Private)'=='true'"> -->
    <!-- ItemName defines the name of the item list. Who came up with this syntax? -->
    <!-- <Output TaskParameter="Include" -->
    <!-- ItemName="_CopyLocalReferencesAgain"/> -->
    <!-- </CreateItem> -->
    <!-- <Message Text="Copy CopyLocal references again: @(_CopyLocalReferencesAgain)" /> -->
    <!-- <Copy SourceFiles="@(_CopyLocalReferencesAgain)" -->
    <!-- DestinationFolder="$(OutputPath)" SkipUnchangedFiles="true"> -->
    <!-- </Copy> -->
  </Target>
</Project>

MSI und Bootstrapper Setups

Die MSI Setups (WIX) und WIX-Bootstrapper-Setups funktionieren ein wenig anders um ihre Versionsnummer eingeimpft zu bekommen. Da es aber MSBUILD-Projekte sind, kann man ähnlich vorgehen. Quelle der Inspiration: Dieser Stackoverflow Artiel.

  1. In der Projektdatei *.wxiproj muss dieser Teil relativ an den Anfang. Hier wird die Umgebungsvariable als ‚Version‘ genommen. Bei fehlender Variable gibt es einen Fallback. Auf diese Weise gibt es immer eine gesetzte Version. Ansonsten scheitert der WIX-Build.
    <!-- define version constant if CI-Build not running  use a default -->
    <Version Condition=" '$(BuildVersionOfAssembly)' == '' ">5.99.99</Version>
    <Version Condition=" '$(BuildVersionOfAssembly)' != '' ">$(BuildVersionOfAssembly)</Version>
    <DefineConstants>Version=$(Version)</DefineConstants>
  1. In die Dateien *.wxs nutzt man die soeben gesetzte Variable (Verfpgbar als $(ver.Version)).

Beispielausschnitt einer *.wxs:

  <Product Id="CDE4C223-7A78-45FF-A984-675F414BD516" Name="!(loc.PRODUCT)" Language="1033" Version="$(var.Version)" Manufacturer="!(loc.MANUFACTURER)" UpgradeCode="cae20b70-d924-4b23-b90e-9ea1b5f5026b">
    <Package InstallerVersion="200" Manufacturer="!(loc.MANUFACTURER)" Compressed="yes" Description="!(loc.PRODUCT) $(var.Version)" />
    <Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
    <Property Id="TAKEBACKUP" Secure="yes" />
    <Upgrade Id="cae20b70-d924-4b23-b90e-9ea1b5f5026b">
      <UpgradeVersion Minimum="$(var.Version)" IncludeMinimum="no" OnlyDetect="yes" Language="1033" Property="NEWERPRODUCTFOUND" />
      <UpgradeVersion Minimum="0.79.0" IncludeMinimum="yes" IncludeMaximum="no" Maximum="$(var.Version)" Language="1033" Property="UPGRADEFOUND" />
    </Upgrade>

Release

Zu einer Build-Pipeline gehört immer auch eine Release-Pipeline. Die soll aber nicht das Thema dieses Betrags werden. Hier ging es vornehmlich um das korrekte Errechnen und setzen von Assembly-Versionen und MSI-Versionen.

Als Bemerkunt oder Tip sei hier nur gesagt: Eine Build-Pipeline erzeugt Artefakte (irgendwo in Azure in einem Storage). Diese kann man im DevOps zwar herunterladen und damit arbeiten. Aber die verschwinden irgendwann. Daher benötigt man eine Release-Pipeline. Damit macht man eigentlich eher ‚Deployments‘ und Tests von Software. Man kann aber auch einfach eine leere Pipeline anlegen und einfach nur einen Copy-Task anlegen. Wenn der passende Agent ‚inhouse‘ läuft, kann man dann die Buildartefakte auf einen netzlokalen SMB-Share kopieren.

Fazit

Wir haben hier gesehen, wie man dynamisch beim Build eine jeweils neue Version errechnet und damit eine DevOps-Pipeline-Variable setzt und diese dann erfolgreich in die Buildartefakte (Assemblies und MSIs) hineinbekommt. Dies soll eine Inspiration sein, um jederzeit korrekt versionierte Builds zu haben und MSI-Installer, die automatische Upgrades machen können.

Multi Document Interface mit Angular

Problemstellung

Es geht in diesem Beitrag um eine Möglichkeit, in einer ASP.Net+Angular-Anwendung mehrere Dokumente und die Standardnavigation darzustellen. Man stelle sich vor, es wird eine Business-Anwendung in Angular entwickelt und diese kann z.B. Akten anzeigen. Zusätzlich hat sie aber, wie jede vernünftige Anwendung, eine Navigation über diverse Bereiche. Was man also will, ist: Es gehen für die Akten eigene Tabs auf und in einem „Haupt-Tab“ wird weiterhin die übliche Navigation durchgeführt (z.b. Profileinstellungen, andere Aspekte der Anwendung). Hier zeige ich das Beispielhaft an einer von mir entwickelten ASP.Net + Angular- Anwendung (auf Basis von ABP). Es sollte sich aber leicht auf alle Angular-Anwendungen übertragen lassen.

Router

Kurze Rekapitulation, wie man in Angular Navigiert. Die Anwendung wird als eine Hierarchie von Komponenten (components) definiert. Typischerweise mit *.html*-Dateien. Irgendwo befindet sich darin ein Element *<router-outlet></router-outlet>*. Hierdurch weiß der *Router* von Angular, dass an dieser Stelle die Komponenten des Routing-Ziels eingeblendet werden sollen. Was dann auch passiert.

Tatsächlich kann man mehrere *router-outlet*s definieren. Die Weiteren müssen individuelle Namen haben. Dann kann man mit einer tollen URL-Syntax mit Doppelpunkten und Outlet-Namen für alle Outlets gleichzeitig verschiedene Komponenten „ernavigieren“. Allerdings hat sich das meinen Kenntnissen und meiner Vorstellungskraft entzogen… Also ob man nur einzelne Outlets ändern kann, derweil der Rest bleibt und wie man dann dynamisch mehr und mehr solche Outlets erstellt (die Tabs) und auch wie man sie sinnvollerweise dann benennt. Also dieser Ansatz wurde ad Acta gelegt.

Der Ansatz

Datenhaltung

Wie sollte das Ganze sinnvoll gestaltet werden? Die Idee wäre, dass man ein Objekt hat, welches die Tabs als Datenstruktur enthält und einige Methoden bietet, um die Tabs zu verwalten. Ich habe es als Singleton realisiert. Es kann aber, je nach Architektur, auch sinnvoll sein, mehrere davon zu haben. Z.B. wenn man mehrere Tabs aufbauen will. Dann muss aber irgendwie das „default“-Router-Otulet abschaltbar werden.

Wir brauchen auf alle Fälle einen injezierbaren Service (@Injectable), der in den verschiedensten Modulen der Anwendung verfügbar ist und die Tabs programmatisch modifizieren kann. Zusätzlich muss er aber auch für die Darstellungskomponente verfügbar sein.

Code von src\app\shared\layout\open-document-service.ts:

import { Injectable,
    Inject,
    Type,
    ReflectiveInjector,
    ViewContainerRef, 
    Injector } from '@angular/core';
import { AppComponentBase } from '@shared/common/app-component-base';

// Injezierbarer Service, um auf die globale Definition
// der Tabs zuzugreifen und zu manipulieren
@Injectable()
export class OpenDocumentService {
  
    constructor(private _inj : Injector)
    {
    }

    offeneDokumente: Array<Dokument> = [  ];

    addTab(d:Dokument){
        let newId = d.id;
        const i = this.offeneDokumente.findIndex( elem=>elem.id == newId);
        if(i > -1)
        {
            // Tab aktivieren
            this.offeneDokumente[i].active = true;
            return;
        }

        // sonst kann es hinzukommen
        this.offeneDokumente.push(d);
    }

    // remove a tab
    remove(id: string) {
        const i = this.offeneDokumente.findIndex( elem=>elem.id == id);
        this.offeneDokumente.splice(i, 1);
    }
}

export class Dokument {
    public titel : string;
    public id: string;
    public removable : boolean;
    public disabled : boolean;
    public active : boolean;
    public compref: any;
}

Hier werden die Tabs in einem TS-Array gehalten und es gibt simple und eventuell verbesserbare Methoden zum Hinzufügen und entfernen. Als Struktur wurde die neue Datenklasse Dokument eingeführt, die eien Tab repräsentiert.

Darstellung

Das Ganze muss natürlich irgendwie Dargestellt werden. Zunächst steht das Control, das zur Realisierung genommen wird. Dabei habe ich mich für TabsetComponent von „ngx-bootstrap“ entschieden. Eingebunden wird das über eine neu zu erstellende Komponente in die Anwendung. Nennen wir das Teilchen mal *multdoc-control*. Im Prinzip ist diese Komponente nichts anderes als eine geschickte Tab-Definition mit ngFor. Der immer vorhandene Tab ist das „default“ *router-otulet*; und der Rest ist die per ngFor definierte Magie, mit der die offenen Dokumente/Akten dargestellt werden.

Code von src\app\shared\layout\multi-document.component.ts:

import { Component, ViewContainerRef, ViewChild } from "@angular/core";
import { OpenDocumentService, Dokument } from "./open-document-service";
import { ContentPresenterComponent } from "./content-presenter.component";
import { TabsetComponent } from "ngx-bootstrap";

// Das ist so ziemlich nur eine GUI (html zusammenfassung) Komp.
// https://valor-software.com/ngx-bootstrap/#/tabs
@Component({
    template: `  
    <div>
        <tabset #mainTabs>
            <tab heading="Titel">
                <router-outlet (activate)='onOutletActivate($event)'></router-outlet>
            </tab>

            <tab *ngFor="let tabz of offeneTabs.offeneDokumente"
                [heading]="tabz.titel"
                [active]="tabz.active"
                (selectTab)="tabz.active = true"
                (deselect)="tabz.active = false"
                [disabled]="tabz.disabled"
                [removable]="tabz.removable"
                (removed)="removeTabHandler(tabz)"
                [customClass]="tabz.customClass">
                <content-presenter [component]="tabz.compref"></content-presenter>
            </tab>
        </tabset>
    </div>`,
    selector: 'multi-document-component',
    providers: [
        OpenDocumentService,
    ],
    viewProviders: [ ContentPresenterComponent ],
})
export class MultiDocumentComponent  {

    @ViewChild('mainTabs') mainTabs: TabsetComponent;
    offeneTabs: OpenDocumentService

    constructor(private _vcr: ViewContainerRef,
         offeneTabs : OpenDocumentService)
    {
        this.offeneTabs = offeneTabs;
    }
     
    removeTabHandler(tab:Dokument){
        //alert("REM: tabid " + tab.id);
        this.offeneTabs.remove(tab.id);
    }
    
    onOutletActivate(ev): void {
        this.mainTabs.tabs[0].active = true;
    }
}

Hier ist also relativ geradelinig das router-outlet und die dynamische Definition der weiteren Tabs. Da so wenig HTML dabei ist, ist alles in eine .ts-Datei gewandert. Dazu noch einige Events, wie z.B. dass bei Start der erste Tab mit dem router-outlet aktiviert wird. Nur, wie werden diese Tabinhalte Dargestellt und on-demand erstellt? Also erst bei Tab-Klick die korrekte Komponente gefunden und eingefügt? Die Lösung ist mein selbst entwickelter Contentpresenter. Hier sieht man recht klar meine Herkunft aus der WPF-Welt. Die hat mir dabei durchaus genutzt, vielleicht hätte es aber auch eine direktere Angular-Lösung gegeben.

Code von src\app\shared\layout\multi-document.component.ts:

import { Component, OnInit, 
    ViewContainerRef, AfterViewInit, ViewChild, 
    Input, 
    ComponentFactoryResolver, Inject, ViewRef, OnDestroy } from "@angular/core";
import { OpenDocumentService } from "./open-document-service";

// Komp. wie ein ContentPresenter
// https://medium.com/front-end-weekly/dynamically-add-components-to-the-dom-with-angular-71b0cb535286
@Component({
    template: `<ng-template #dynamic></ng-template>`,
    selector: 'content-presenter',
    providers: [
        OpenDocumentService,
    ]
})
export class ContentPresenterComponent implements AfterViewInit, OnDestroy   {
    @ViewChild('dynamic', { 
        read: ViewContainerRef 
      }) viewContainerRef: ViewContainerRef

    // This property is bound using its original name.
    @Input() component: any;
    factoryResolver: ComponentFactoryResolver;

    constructor(
          @Inject(ComponentFactoryResolver) factoryResolver: ComponentFactoryResolver)
    {
        this.factoryResolver = factoryResolver;
    }

    ngAfterViewInit() {
        let view: ViewRef = this.component.hostView
        this.viewContainerRef.clear();
        this.viewContainerRef.insert(view);
        view.detectChanges();
    }

    ngOnDestroy(): void {
    }
}

In ngAfterViewInit() passiert die Magie. Generell wird eine Komponente im gewählten Tab-Control erst initialisiert, wenn sie angezeigt wird. Das ist aber eine Eigenschaft des Tab-Controls. Dann aber wird die eigentliche Zielkomponente, wie sie in compref übergeben wird, einfach nur an dieser Stelle eingefügt. Sicherheitshalber wird vorher der alte Inhalt gelöscht. Zuvor muss aber der Tab-Inhalt von irgendwem erzeugt worden sein. Dazu wird die passende „Factory“ über den ComponentFactoryResolver (angular Komponente) gesucht und die Komponente erstellt. Siehe dazu den Teil Verwendung. Wichtigster Teil hier ist die Angular-Komponente <ng-temlpate>. Sie kann im TS-Code gefunden werden und mit beliebigen anderen Views gefüllt werden.

Test

Jetzt haben wir alle Teile zusammen und können alles zusammenfügen und ausprobieren. Zum Test bietet es sich an, sich eine kleine Testkomponente zu erstellen, die möglichst wenige Abhängigkeiten hat. Hier ist ein Beispiel dafür:

import { Component, OnInit, Input, OnDestroy } from "@angular/core";

// eine Testkomponente
@Component({
    template: `  
    <div>
        Ich bin ein Test von ID={{id}}
    </div>`,
    selector: 'test-component',
    viewProviders: [  ],
})
export class TestComponent implements OnInit, OnDestroy  {
    @Input() id: string;
    
    ngOnDestroy(): void {
        alert("OnDestoy TestComp:" + this.id);
    }
    
    ngOnInit(): void {
    }
}

Durch das Implementieren von OnDestroy wird die Methode ngOnDestroy() bei Entfernung aufgerufen. Das soll durch alert() veranschaulicht werden.

Verwendung

Einbindung

Die Einbindung der neuen Multi-Dokument-Komponente sieht wie folgt aus. In meinem Fall ist es in einem ABP-Theme geschehen. Grundsätzlich gilt es, alle Vorkommen von <router-outlet> durch <multi-document-component> zu ersetzen:

        ...
        <div class="m-grid__item m-grid__item--fluid m-wrapper">
            <multi-document-component></multi-document-component>
        </div>
       ...

An dieser Stelle sei erwähnt, dass bei Angular wirklich die XML-Elemente in der Form von öffnendem und schließendem Teil geschrieben werden müssen. Sonst geht es nicht.

Steuerung

Gesteuert wird die Tab-Komponente über die injezierbare Datenhalter-Instanz. Dazu muss diese zunächst als Injectable eingebunden werden und dann kann man sie zum Beispiel so verwenden:

import { Component, Injector, ViewEncapsulation, ViewChild, Input, Type, ComponentFactoryResolver, ComponentRef } from '@angular/core';
import { OpenDocumentService, Dokument } from '@app/shared/layout/open-document-service';


...

    //--Constructor-------------------------------------------------
    constructor(
        injector: Injector,
        private _fr:ComponentFactoryResolver
        ...,
        private _openDocSrv: OpenDocumentService,
    ) {
        super(injector);
    }

addAkteToView(ka: KarteiDto): void {

        const factory = this._fr.resolveComponentFactory(TestComponent);
        
        const componentref: ComponentRef<TestComponent> = factory.create(this._injector);
        componentref.instance.id = ka.id;

        let dokument:Dokument = {
            active: true,
            titel: ka.akte,
            disabled:false,
            removable:true,
            id: ka.id,
            compref: componentref,
        }
        this._openDocSrv.addTab(dokument);
    }

In dieser ‚anderen‘ Komponente wird die einzufügende Komponente (TestComponent) aufgelöst, erzeugt und eingefügt. Also nicht im Contentpresenterdaselbst, sondern hier. Dazu braucht man den Injector und die den ComponentFactoryResolver. Nach dem Resolve kann die neue Komponente angesprochen werden und vermittels einem passenden Dokument-Objekt in den OpenDocumentService eingefügt werden. Das Ergebnis ist sofort sichtbar. Die Elementvariable compref übergibt die eigentliche Komponente.

Gedanken

Ich hatte im ersten Moment natürlich schon geplant, die Instantiierung der View im Tab in diesen ContentPresenter hineinzulegen. Tatsächlich ist der Stand ja, dass die „tabanlegende“ Komponente die View instantiiert. Vorteil dieser jetzigen Vorgehensweise: Man kann die neue Komponenteninstanz, die in den Tab hineinkommt, noch weiter konfigurieren. Also an der Stelle im Code, wo das meiste Fachwissen zu dieser Komponente vorhanden ist. Würde man die Komponente im ContentPresenter instantiieren, könnte man sie nicht individuell konfigurieren – man bräuchte beispielsweise einen weiteren Callback. Diesen Weg wollte ich durchaus beschreiten, bin aber letztendlich ein wenig vor der höheren Komplexität zurückgeschreckt (war bei dieser Lösung auch nicht nötig) und ich habe es syntaktisch nicht hinbekommen, den generischen Typ ComponentRef<Comp> und den Typ Comp parametrisch in eine Schnittstelle zu gießen, sodass dieser Zweisatz funktionieren könnte:

const factory = this._fr.resolveComponentFactory(Comp);
const componentref: ComponentRef<Comp> = factory.create(this._injector);

Indien – eine kurze Einführung

Hier nun mein kurz und knapp reisehinweise. Zu Indien. Wie immer wichtig sind Internet Mobil und Geld.

Anreise

Praktischerweise reist man mit dem Flugzeug an und weil Delhi eh die schlechteste Luft aller Städte hat, sind auch dorthin die Flüge am günstigsten. Tja, vielleicht nicht deshalb, aber im Jahr 2019 bot es sich an, einen Hin- und Rückflug via Delhi zu machen, irgendwo hin zu reisen und von irgendwo einen Einwegsflug nach Delhi zu nehmen, um zurückzukehren.

Geld

Bezüglich Geld ist Indien ein ganz normales Land, welches im SWIFT System dabei ist. Man geht mit seiner Karte an einen Automaten (ATM) und bekommt Geld. Wie in anderen Ländern auch, gibt es auch in Indien Geldautomaten, die mit internationalen oder auch nur fremden Karten anderer Institute nichts anfangen können. Dann gibt es etliche die 200 Rupien Gebühr wollen. Um die solle man einen Bogen machen, denn es gibt genügend Automaten, die keine Gebühr verlangen. Davon im Weiteren eine unvollständige Liste. Aktuell, zum Zeitpunkt des Schreibens, konnte man maximal 10.000 Rupien pro Vorgang abheben. Das waren damals ca. 128€. Ein durchaus sinnvoller Wert. Als Karte für Auslandsreisen empfehle ich nach wie vor die VISA-Kreditkarte der comdirekt.de. die erlaubt es quasi gratis Geld abzuheben. Keine auslandsgebühr und keine Automatengebühr. Abrechnung fast zum Tagesmittelkurs.Bekannt gute Banken:

  • SBI (State Bank of India)
  • IndusInd Bank
  • Baroda Bank
  • HDFC Bank
  • Dhanlaxmi Bank

Mobilfunk

Es geht doch nichts über die Nützlichkeit von mobilem Internet an der Hand und zu jeder Zeit. Insofern plädiere ich schon lange für simkarten wo immer man ist.Indien ist diesbezüglich, wie in vielen Dingen, bürokratisch und etwas komplizierter. Natürlich muss man seinen Pass vorzeigen und sich registrieren. Mit auf der Straße einfach so kaufen iss nich. Könnte ja sonst auch jeder Terrorist was schlimmes damit machen…Daher kann aber nicht jeder Laden so eine SIM-Karte ausgeben. Es empfiehlt sich daher, gleich den oder die Läden am Flughafen zu nutzen. Ich kann nur zu Delhi berichten. Angeblich gibt es im Ankunftsbereich einen Air-Tel und einen Vodafone-Laden. Beide habe ich zusammen mit einem Freund nicht entdeckt. Stattdessen sind wir am ersten Tag zum Conought-Place und haben den dortigen (haupt-)Vodafone-Laden aufgesucht, da dieser als einer der wenigen auch mit fremden Pässen umgehen kann. Das war dann auch eine Prozedur. Eben typisch indische Überbürokratie. Man muss nämlich neben dem Pass auch das E-Visa und ein Foto mitbringen. Dankenswerterweise nutzt man Vorort Kopierer und kopiert die Pässe und E-Visa und kann sogar Bilder machen. Kosten? Kopie nix; Bilder hatte ich dabei. Nach endlosen Formularen und Papier und getackere bekommt man irgendwann eine SIM-Karte. Die muss dann noch aktiviert, aufgeladen und der passende Tarif gewählt werden. Zum Glück macht das alles der Mensch im Laden für einen. Sonst würde das ja noch länger dauern. Aber deshalb gibt es ja auch handgeschriebene Wartemarken – ganz wie auf dem Amt. Der Tarif ist dagegen recht gut: Für umgerechnet 9€ hatte ich 28 Tg. 1,5GB Internet und 4G sowie 500 Minuten Gespräch.

Strom

Der Strom ist in Indien kompatibel. Mit seinen 240V 50 Hz hat er zwar 10V mehr, aber das macht nichts. Von den Steckern her ist es verwirrend aber praktisch problemlos. Eigentlich hat Indien den alten britischen Standard bei sich im Einsatz. Das sind zwei Stecker, wo die Pinne im Dreieck angeordnet sind. Einmal dicker und einmal etwas runterskaliert. Indien hat im Gegensatz zu vielen anderen Ländern nie den modernen britischen Standard (den mit den rechteckigen Pinnen) adaptiert. Allerdings ist fast überall eine von zwei verschiedenen Universalsteckdosen zu finden. Die nehmen entweder den kleinen indischen Stecker auf oder US oder EU-Stecker sowie manche auch britische. Oder man bekommt den EU-Stecker auch in die kleine indische Steckdose hinein.

Aber: Wenn man sich mal ansieht, wie der Strom so verlegt ist, könnte einem als Elektriker schlecht werden. Als „Normalo“ sollte einem dabei so mulmig werden, dass man ständig in einer gewissen Hab-Acht-Stellung ist. Denn es hängen Drähte und Kabel überall herunter oder so tief, dass man sie mit dem Kopf berühren kann. Das Gute ist: Es handelt sich fast immer um tote Datenkabel, die so oder so harmlos sind. Doch: Man weiß eben nie. Daher lautet das Gebot: Berühre nichts, was von oben herabhängt. Achtung ist auch geboten bei allen elektrischen Verteilungen. Ob Trafostation oder Hausanschluss. Überall findet man nicht-berührsicher ausgeführte Ekeltroinstallationen. Also berührbare spannungsführende Teile, die im Zweifelsfall tödlich sein können. Daher: Immer einen gesunden Abstand wahren.

Wasser

Wasser oder die Wasserqualität ist das große Problem von Indien. Ein hygienisch gefährliches Land unterscheidet sich von einem hygienisch ungefährlichen anhand der Qualität des Leitungsnetzes und der Wasserqualität. Beides ist in Indien desolat. Das Wasser in Indien muss als bakteriell kontaminiert angenommen werden. Also wascht euch damit bestenfalls ab, aber nutzt es nicht zum Zähne putzen und schon gar nicht zum Trinken. Also Zähne putzen mit der PET-Wasserflasche. Doch auch da gilt es aufzupassen, denn es soll Fälle gegeben haben, wo vom Händler eigenhändig wiederbefüllt wurde. Tee oder andere gekochte Getränke sind OK. Also auch im Hotel den Wasserkocher benutzen etc. Tip: Tassen einmal mit kochend heißem Wasser ausspülen. Auch Teller, die noch Wasserreste drauf haben sind potentielle Keimüberträger. Das gute: Trockenwischen und 3min der Luft aussetzen reicht i.d.R. aus um sicher zu sein.

In Restaurants wird i.d.R. Wasser aus Kannen angeboten. Für Inder ist das wunderbar geeignet, für uns ‚Westler‘ eher nicht. Vermutlich passiert nichts, aber besser man bleibt auf der sicheren Seite.

Hotelerie

Indien ist so ein naja, komisches Hotelland. Zunächst gibt es sehr viele Hotels zu auch sehr günstigen Preisen und auch viele Kategorien. Man könnte jetzt positiv sagen, für jeden sei Etwas dabei. Man findet also auf den üblichen Hotelbuchungsportalen viel Auswahl, aber nicht alles. Insbesondere ist booking.com und Expedia (hotels.com) nicht vollständig. Macht aber nichts. Die meisten Hotels gehören Leuten, die da nie selbst „Im Laden“ stehen oder Ketten. Betreut werden sie auch eher von „durchschnittlichen“ Menschen. Ego ist es nicht sonderlich erfolgreich, eine Buchung per Telefon zu machen. Insbesondere kommt man nicht billiger ‚raus, als wenn man via Buchungsportal geht. Das verwundert zunächst, heißt aber, dass die Angestellten dort nichts zu sagen haben und die Preise woanders gemacht werden. Daher: Um Missverständnisse zu beseitigen und klare Preisangaben zu haben, sollte man in Indien über Buchungsportale wie booking.com und Hotels.com gehen. Tatsächlich wird es so günstiger als direkt.

Die Qualität ist eine andere Sache. Man sollte auf jeden Fall auf Buchungsportalen vergleichen. Es gibt immer wieder gute Preisbrecher. Aber gegen schimmlig und schlecht gewartet ist leider kein Kraut gewachsen. Bilder kann man nicht riechen und Bilder werden auch sehr gerne stark geschönt. Da kommt dann die große reale Ernüchterung. Es empfiehlt sich daher jeweils nur eine Nacht zu buchen, um die Kosten und Zimmerart festzulegen und dann nach Bedarf verlängern. Schimmel und übel ungewartete Hotels sind leider häufiger als einem lieb ist und bei den Angestellten dann leider auch überhaupt kein Bewusstsein dafür da.

3 Monate im Jahr Urlaub

Wie geht das denn? 12 von 52 Wochen. Das klingt ja schon fast wie die berühmte 4-Stunden-Woche.

Als Angestellter wird 3 Monate Urlaub eher nichts, außer man macht einfach unbezahlten Urlaub. Als Freiberufler oder Gesellschafter-Geschäftsführer klappt das schon eher, wobei man als Freiberufler in seinem Urlaub eigentlich gar nichts verdient. Aber wie es eben so ist als Selbständiger: Man verdient ja etwas mehr als ein Angestellter und muss sich seinen Urlaub selbst hin-finanzieren. Wenn man es richtig anstellt, reichen 8 Monate Arbeit, um sich die restlichen 3 Monate ein sein kalkulatorisches oder im Geschäftsführer-Fall sein tatsächliches Gehalt zu zahlen.

Urlaubskosten

Wohl die Rechnung ohne den Wirt gemacht? Urlaub ist doch immer teuer und dann noch in einer Zeit, in der man irgendwie ja nichts verdient. Das ist schon richtig. Urlaub kann sehr teuer sein, aber er kann auch recht günstig sein. Ich habe es aufgrund meiner Länderwahl zuletzt immer geschafft, weniger Geld auszugeben, als wenn ich daheim geblieben wäre. Das ist natürlich auch nicht ganz richtig, weil ja die Miete für die Wohnung weiter läuft. Aber wenn wir die mal als Grundkosten Beiseite lassen, dann lässt sich durchaus pro Tag mit weniger Geld zurechtkommen, als in Deutschland. Daher empfehle ich Balkan, Osteuropa und Süd-Ost-Asien als gute Reiseländer.

Machen

Vor allem aber ist es mal wieder eine Mentalitätssache. Man traut sich nicht, länger unbezahlten Urlaub zu machen, oder ohne Folgeprojekt in einen 2-Monatigen Urlaub zu gehen etc. pp. Aber an dieser Stelle muss man einfach seine Bedenken über Bord werfen und es machen. Mut zur Lücke. Viel passieren kann nicht. Wenn man so jedes Monat gut über die Runden kommt, dann auch in einem Reisemonat. Auf geht’s.

Monopoly – Das Phänomen

Monopoly, das Spiel. Das, das jeder kennt und vermutlich schon einmal gespielt hat. Das Phänomen. Warum, Phänomen? Weil es soo ein schlechtes Spiel ist, und dennoch wohl das meistverkaufte jemals ist. Schlimmer nich: Das Spiel existiert in unzähligen Varianten. Es gibt Varianten für diverse kleine und große Städte, Disney, Länder, Filme. Vor allen aber ist Monopoly irgendwie immer eines der Spiele, die im Verkaufsregal zu finden ist, egal wie klein die Spieleabteilung ist. Traurig. Am Ende aber ist das Spielprinzip immer gleich… gleich schlecht, wie ich finde.

Schlechtes Spielprinzip

Gute Spiele zeichnen sich dadurch aus, dass ein gewisses Machtgleichgewicht bis mindestens zur Hälfte der Spielzeit besteht. Das kann dadurch erreicht werden, dass es mehrere gleichwertige Strategien gibt, mit denen man das Spiel gewinnen kann, statt nur einer. Bei Monopoly ist genau das nicht der Fall. Das Gleichgewicht kippt sehr früh im Spiel und von da an Belgier m verstärkt sich das Ungleichgewicht zusehends. Recht bald macht das Spiel nur mehr einem Spieler Spaß, der Rest muss im wahrsten Sinne gute Mine zum bösen Spiel machen. Aus diesem Grunde ist Monopoly für mich eines der schlechtesten Spiele und das schlechtest- und meistverkaufte Spiel der Welt. Echt traurig.

Appell

Daher bin meiner Seite der Appell am alle Spieler und Schenkenden. Spielt nicht dieses Spiel, egal welcher Variante; es bedeutet nur Frust und hat in der Regel nichts mit Können oder Unvermögen zu tun. Und bitte kauft es nicht und verschenkt es nicht… vor allem nicht in der 100-sten Variante. Lasst die Kisten in den Verkaufsregalen verrotten!

Grenzübertritt Turkmenistan-Usbekistan

(bei Farab)

Ein Erfahrungsbericht über das Passieren der Landgrenze von Turkmenistan nach Usbekistan. So ist es uns ergangen. Unsere Zeit: ca. 1:15 h. Unterwegs zu Fuß zu zweit mit je einem Koffer/Rucksack. Bei Euch kann es natürlich völlig anders laufen und vielleicht Stunden dauern.

Aufbau

Der Grenzübergang zwischen den beiden Ländern ist für diese Region vielleicht typisch, aber im Vergleich zu Europäischen Grenzübergängen schon ziemlich aufwendig. Man kann ihn grob in 7 Stationen einteilen. Hier eine Übersicht:

Satelitenansicht des Wegs über die Grenze
Grenzanlage Farab

Prolog aka. Station 0 (TM)

Eigentlich beginnt die Grenze schon auf der Brücke 2km davor. Wie im ganzen Land gibt es auch hier einen Polizeicheckpoint. Hier am Checkpoint lässt man nur Leute durch, die zur Grenze wollen. Pässe bereitlegen.

Station 1 – Checkpoint (TM)

Hier vor der Schranke wurden wir von unserer Tour (ja die braucht man in Turkmenistan) abgesetzt. Vor der Schranke stand eine Traube von ca. 25 Leuten in ca. 40°C und praller Sonne und wollten durch. Der Checkpoint aber verweigerte es bis auf Weiteres. Wir machten uns schon mal auf Etwas gefasst. Aber kaum das klar wurde, dass wir Touristen waren und EU-Pässe in Händen hielten, wurden wir zum Schalter gebeten. Ein Militärmensch schrieb manuell unsere Passnummern und Namen in ein Buch ein. Sodann durften wir zu den anderen, auf das „Taxi“ wartenden ca. 20 Leuten rübergehen. Das „Taxi“ ist ein alter Barkas und musste erst einmal kommen. Um Zeit und Geld zu sparen, wollten wir die 800m zu Fuß gehen, was uns aber verweigert wurde. Entweder aus Ungläubigkeit oder aus Angst, wir könnten vom Weg abkommen. Also warteten wir auf die Wiederkehr des Barkas‘. In der zweiten Fuhre konnten wir mitfahren. Es kostete je 1 Manat, was ca. 6ct entsprach. Wahlweise wurde auch 1 USD genommen (höhö).

Station 2 – Grenzkontrolle (TM)

Die eigentliche Ausreise. Wir kamen in dem 800m entfernten Gebäude an und mussten kurz anstehen, da vor dem Ausreiseschalter zu viele Menschen standen (Stau). Dann ging es los mit Gepäckscan. Nicht sonderlich gründlich – einfach durch da. Unklar, ob überhaupt jemand auf den Bildschirm geschaut hat. vor uns war der Schalter mit dem Beamten, der die Ausreisestempel einstempelt. Davor eine Menge von ca. 34 Turkmenen, die chaotisch mit Ihren Pässen in den Händen um „Abstempelung“ flehten. Der Beamte schob ruhig seinen Dienst. (Anstellen in einer Reihe war hier wohl nicht vorgesehen). Ein Beamter vom Scanbereich eilte herbei und machte uns einen kleinen Zugang zu dem Schalter frei, wo wir auch prompt unsere Pässe hineingeben sollten. Nachdem der Stempel-Mensch mit den aktuellen Turkmenen-Pässen fertig war, kamen auch schon unsere dran – das ging merklich schneller als mit dem turkmenischen Pass. Mit abgestempeltem Visum konnten wir das Gebäude wieder verlassen und mussten davor auf das nächste „Taxi“ (ebenfalls ein alter Barkas) warten. Zum Glück gab es hier Schatten. Das „Taxi“ kam auch recht bald. Es stand wieder eine Traube von Menschen bereit zum Einsteigen. Wir waren uns schon sicher, hier auch erst mit der zweiten Fuhre mitzukommen. Doch der Fahrer bekam irgendwie Wind von unserem Touristen/EU-Status und bat uns an der wartenden Menge vorbei, als erstes einzusteigen. Uns war es ein wenig peinlich aber auch hier wollten wir nicht lange zögern. Das Einsteigen gestaltete sich dann etwas „stapelig“ und der Fahrer bekam auch einmal so derart die Unruhe, dass er den Motor abstellte. Scheinbar hat sich jemand schlecht behandelt gefühlt und wollte ob überladener Verhältnisse unbedingt noch mitsamt Koffer mit. Irgendwie ging es.

Station 3 – Demarkationslinie (TM)

Die Fahrt ging vorbei an unzähligen wartenden LKW. Nach dem Aussteigen standen wir ein letztes Mal vor einem Durchgang mit turkmenischem Beamten. Dieser checkte noch einmal, ob auch wirklich ein Stempel im Pass war. Wartezeiten gab es hier kaum, da es jeweils schnell ging und nur diese Autoladung da war.

Station 4 – Demakrationslinie (UZ)

Direkt 2m dahinter stand der erste usbekische Beamte. Der musste natürlich auch den Pass anschauen. Dabei ging es wohl nur um die generelle Frage ob es ein gültiger für Usbekistan ist.

Station 5 – Gesundheitsamt (UZ)

Auf usbekischer Seite kommt man nach einigen Decametern (10m) zunächst in ein längliches Haus, wo am ersten Schalter ein Arzt stand. Der schaute auch kurz auf den Pass und waltete seines Amtes insofern, als dass er die Körpertemperatur maß. Er tat dies mit einem berührungslosen IR-Scanner. Wenn das durch ist, geht man noch an 2 leeren Schaltern vorbei und nach einer kurzen Hofüberquerung landet man in…

Station 6 – Einreise und Zoll (UZ)

Das ist wieder ein ordentlicheres Gebäude. Man läuft auf einen Doppelschalter zu, bei dem 1-2 Grenzbeamte die Einreise mit Einreisestempel erledigen. Das geht recht kurz und Schmerzlos. Man wird (in unserem Fall) in schlechtem Englisch durch eine kaum schalldurchlässige Glaswand noch auf ein wichtiges Detail hingewiesen: Die Registrierungszettel der Hotels sind tunlichst aufzuheben, sonst gibt es Probleme.
Der hintere Teil der Halle gilt wieder der Sicherheit respektive wider der Einfuhr illegaler Produkte. Der Rucksack muss abermals auf einen Gepäckscanner. Danach entscheiden noch zwei Beamte mit Tischen vor sich, ob sie in dreckiger Unterwäsche wühlen wollen, oder nicht. Potentiell lassen sie EU-Bürger eher in Ruhe. Ein kleines Gespräch darüber, was man vor hat, und ob man Drohnen einführen will, wird man wohl nicht vermeiden können. Wir wurden bei der Gelegenheit auch nach dem Wohlbefinden von Hitler gefragt. Ich konterte: „Dem geht‘s jetzt ganz gut, der ist letzte Woche gestorben“. Nach einigen weiteren Wortwechseln durften wir den Bau verlassen.

Station 7 – der letzte Checkpoint

Kurz bevor man Usbekistan als freier Mensch betreten darf, kommt noch ein Posten. Der schaut dann nochmal im Pass nach, ob auch wirklich ein aktueller Stempel für Usbekistan drin ist.

Der Taxistand

Direkt hinter der Grenze endet die Straße von Buchara. Hier befindet sich ein Taxiplatz und die Endstation diverser Kleinbusse (Marschrutka). Taxifahrer wollen für die ca. 100km nach Buchara 50 USD oder auch 50 EUR. Mit dem Faustpfand, auf jeden Fall per Sammeltaxi ersteinmal nach Olot zu fahren, konnten wir einen Taxifahrer dazu bringen, sich selbst auf 20 USD herunterzuhandeln. Dazu haben wir ihm zunächst 10 $, dann 20 $ vorgeschlagen und uns demonstrativ in das Sammeltaxi hineingesetzt.

Meta

Auf usbekischer Seite ist viel weniger los, als auf der turkmenischen Seite. Das Problem liegt eindeutig an der Ausreisestelle in Turkmenistan. Sobald ein Turkmene erfolgreich ausgereist ist, machen ihm die Usbeken wohl keine Probleme mehr. Daher war auf usbekischer Seite wenig los.

Iran individuell. Ein Erfahrungsbericht

Sehr wohl, der Iran ist nicht nur mit einer Reisegruppe, sondern auch individuell bereisbar. Gleich man oder frau doch ein Exot ist. Denn Gruppenreisen gibt es sehr wohl in zunehmender Stückzahl. Dieser kleine Erfahrungsbericht nimmt den Leser mit durch die wichtigsten Fragen und Probleme des Alltags, die so üblicherweise auftreten. Dabei ist zu beachten, dass es so gehen kann, aber auch anders und womöglich besser, da ich keineswegs die Weisheit gepachtet habe und sich die Randparameter jederzeit wieder ändern können. Daher ein Jetztbericht aus 9/2019 – ich mit meiner Frau.

Visum

Für die Einreise in den Iran braucht man ein Visum. Dafür ist nun kein sog. LOI (Letter of Invitation) eines Reisebüros oder Freunde/Familie mehr nötig. Somit steht Individualreisen nichts mehr im Wege. Angeblich bekommt man, bei der Einreise über den Flughafen Teheran, ein „Visa on arrival“. Wir haben das nicht ausprobiert, sondern uns schon vorher mit einem Visum ausgestattet: Auf der modern gestalteten Webseite XXX werden Daten abgefragt und eine Antragsnummer vergeben. Im Prozess werden mehrere PDF zugesendet. Mit einem davon geht man zur Botschaft /Konsulat seiner Wahl (international) und legt den Zettel mitsamt seinem Pass vor. Persönliches Erscheinen ist obligatorisch. Nach Zahlung eines Geldbetrags (in unserem Fall je 55€) war die Sache erledigt. Das elektronische Visum ging einen Schritt weiter und es erreichte uns ein neuerliches PDF.

Einreise

Ich muss leider alle enttäuschen: Die Einreise verlief sehr unspektakulär. Gelandet in Teheran ging es zum Immigrationsschalter. Da wir unsere Passnummern korrekt abgetippt hatten, war es ausreichend einfach nur den Pass hineinzureichen. Damit war die Einreise quasi fertig. Das letzte PDF, verkörpert durch eine A4-Seite musste nicht vorgezeigt werden. Nach Entgegennahme der Koffer gab es noch eine „übliche“ Zollkontrolle, durch die wir ohne weitere Scans o.ä. durchrutschten. Wir hätten ja auch nichts zu verzollen gehabt.

Einen Stempel oder ein schönes Einklebe-Visum gab es ebenfalls nicht. Einerseits gut für eventuelle Israel/USA-Reisen in der Zukunft, andererseits schade für Visasammler.

Geld

Das liebe Geld ist quasi die Achillessehne eines Iranaufenthalts. In „normalen“ Reiseländern geht man mit den tollen „gratis-weltweit-geldabheben-Kreditkarten“ einfach so oft an den Geldautomaten, wie man Kohle braucht und muss sich vorher keine Gedanken machen und „trägt“ auch weniger Risiko mit sich herum. Im Iran ist alles anders. Dank Sanktionen ist der Iran nicht an internationale Geldsysteme (insb. US-Basierte Kreditkarten) angeschlossen. So gibt es zwar im ganzen Land Geldautomaten wie Sand in den landeseigenen Wüsten, aber mit unseren Karten bekommt man dort nichts. Ergo muss man sein gesamtes Reisebudget bar mitbringen. Hotels lassen sich im Übrigen auch nicht „vorbuchen“ im Sinne von „von daheim aus bezahlen“. Es gibt ja keine sinnvollen Finanzströme zwischen der Welt und dem Iran. Ausnahmen bestätigen die Regel.

Daher gilt: Sich vorher über das Tagesbudget Gedanken machen und entsprechend viel Bargeld mitnehmen. Meine klare Empfehlung ist Euro. Das ist das liebste Geld der Wechselstuben. Ist ja auch klar: US-Dollar ist ja das Geld des Feindes – wird aber auch gewechselt. Aber auch so ist Euro empfehlenswert, denn diese Banknoten kommen bei uns direkt und ohne Umrechnungskosten aus dem Automaten. Und im Gegensatz zu US-Dollar dürfen sie auch zerknüllen und verlieren nicht an Aktzeptanz. Tipp: Bei der Volksbank und Deutschen Bank kann man in der Regel die Denomination selbst bestimmen. Es empfehlen sich 100 €-Noten als bester Kompromiss zwischen Verfügbarkeit, Wert und Papiermasse.

Für den Transport haben wir uns für zwei „Sicherheitsgürtel“ entschieden. Gibts im teueren Outdoorfachhandel oder in unserem Falle, das Schnäppchen eines Hamburger Rösterei. Dort passen die Scheine hinein. Je 2 100er auf 1/5 gefaltet passt ganz gut in den Gürtel hinein. Wir hatten so EUR 2000 dabei.

Geldwechsel

Es gibt in jeder größeren Stadt Wechselstuben („Sarafi“). Diese sind staatlich lizenziert und der empfohlene Weg Geld zu tauschen. Pass/Passkopie erforderlich! Auf den Geschäften steht meistens „Exchange“ drauf – da sie aber schwierig zu finden sind, einfach die Einheimischen nach „Sarafi“ fragen. Daneben gibt es noch die „Bazar-Geldwechsler“. Vor denen sind wir gewarnt worden; haben es aber trotzdem getan und sind nicht enttäuscht worden. Nicht empfehlen würden wir aber die fliegenden Geldwechsler auf der Straße. Gefahr eines Neps! Hotels und Hostels wechseln auch Geld und scheinbar auch zur recht respektablen Kursen.

Da die Inflation weiter vor sich geht, und der Scheinmasse wegen, und sowieso sollte man nur immer Stück für Stück wechseln. Je später, desto besser der Kurs. Wir haben mit 1:124.000 angefangen. Was uns bei EUR 100 direkt zu Multimillionären gemacht hat.

Thuman und Rial

Oder die verwirrendste Währung der Welt. Offizielle Währung des Iran ist der Rial. Dank heftiger Inflationsschübe hat man im Alltag mit vielen Nullen zu tun. Immerhin: Mit mehr als 100.000 Rial zu 1 Euro handelt es sich wohl um die wertloseste Währung der Welt. Lange Zeit galt der vietnamesische Dong mit 15000:1 als diese und zwischendrin hatte mal der simbabwe‘sche Schilling diese Krone dank Hyperinflation inne.

Thuman oder Tomann ist komisch. Eigentlich ist es so was wie Euro, derweil Rial die Cent sind. Aber nicht mit Faktor 100 sondern mit Faktor 10. Allerdings tritt der Thuman nicht in Erscheinung. Alle Scheine sind in Rial denominiert. Aber im Alltagsgebrauch lässt der Iraner gerne mal eine 0 weg und sagt statt Rial Thuman. So werden halt dann aus 250.000 Rial 25.000 Tuman. Das ist jetzt nicht unbedingt handlicher, aber man macht das halt schon seit sehr langer Zeit und mit Gewohnheit. Richtig schön wird es bei Preisschildern, denn selten steht dabei was gemeint ist. „Das ergibt sich aus dem Kontext“ – haha(!). Oft kann man einigermaßen einschätzen. Aber dank eines komischen Preisgefüges (Benzin ist mit unter 10ct doch sehr günstig und wirkt sich auf Taxi aus) kann man sich auch mal schnell um den Faktor 10 verschätzen und dann ist mal schnell der Preis zu hoch. In Menükarten steht gerne mal ein „T“ hinter dem Preis.

SIM-Karte und Internet

Wie in vielen Ländern so ist es auch im Iran empfehlenswert bis praktisch, sich eine SIM-Karte zuzulegen. Wir haben uns gleich jeder eine gekauft. Bei einem Preis von 600.000 Rial (5€) für 3GB und 2h Telefon war es keine große Überlegung. Der uns gegebene Anbieter-Tip heißt : Irancell. Angeblich die beste Verfügbarkeit. Bisher unwiderlegbar. Es handelt sich um ein MTN-Unternehmen. Diese Firma operiert auch in vielen afrikanischen Ländern inkl. Schurkenstaaten 😉

Die SIM-Karte sollte man tunlichst sofort am Flughafen kaufen, da es nach Aussagen der einzige Ort ist, wo man sie als Tourist ohne Probleme direkt bekommt. Andernfalls muss man irgendwie einen Iraner einbeziehen und das wird alles eher Mist. Die Karten haben wir daher direkt am Flughafen gekauft. Die freundliche Dame war auch gleich sehr hilfsbereit was die Scheine mit den vielen Nullen an ging und die Einrichtung der Karte, da es nicht sofort ging. Eigentlich gab es kein Problem – man musste wohl einfach nur das Mobiltelefon einmal Neustarten. Allenfalls hier die Einstellungen für den APN (Access Ooint Name) von Irancell: mtnirancell Name ist egal, restliche Einstellungen: leer.

Ab da hatten wir fast überall 4G. Die Geschwindigkeit ist recht gut, da aber auch viele Haushalte über LTE-Router ihr WLAN realisieren, kann es schon mal zu Engpässen kommen. Oft sind daher in Hotels oder Hostels die WLANs schlecht und man weicht besser auf das eigene 4G aus.

Internet und VPN

Da der Iran ja ein autoritäres Regime hat und schon mal richtig Probleme hatte mit der grünen Revolution, sind einige Webseiten und Dienste gesperrt. Das Betrifft z.B. Facebook und Threema. Interessanterweise gehen WhatsApp und Instagram. Hnnn?! Um sich von alle dem unabhängig zu machen, empfehle ich, sich sein eigenes VPN aufzubauen.

VPN? Virtual Private Network. Wer z.B. zu Hause eine Fritzbox stehen hat, kann dort unter Internet-Freigabe ein VPN-Endpunkt einrichten. Die Anleitung, wie man das im Händy einrichtet gibt die Weboberfläche gleich dazu. Am Besten in der Heimat noch einrichten und testen, dann kann im Urlaub in Schurkenstaaten nichts mehr passieren.

Grundsätzlich weiß man nie, was die für ein Schindluder mit dem Internet treiben und was sie einem eventuell hineinschieben. Ich konnte zumindest bisher keine TLS-Manipulation erkennen. Transparente Proxies wären bei HTTP möglich. Daher alles per HTTPS machen! Die Zertifikate waren jedenfalls dieselben wie schon 108 Mal davor. So zumindest Firefox‘ Auskunft.

Transport

Im Iran gibt es zwischen den größeren Städten Autobahn, Landstraße und Eisenbahnverbindungen. In Teheran und Isfahan gibt es eine U-Bahn. Taxis gibt es sowieso überall und Minibus-Verbindungen wohl in jedes Dorf. Auf jeden Fall ist der Transport vor allem günstig und verfügbar. So kostet z.B. ein VIP-Bus zwischen Teheran und Kashan keine 5€.

In Teheran ist fahren mit der U-Bahn der Tipp. Das Netz ist einigermaßen groß und dicht und mit aktuell 25.000 (20ct) pro Fahrt egal wie weit, sehr günstig. In der U-Bahn geht es oft dicht gedrängt zu aber die Straßen oft noch mehr verstopft und so bleibt die U-Bahn das schnellste Mittel um weite Strecken zu machen. Hinten und vorne gibt es jeweils ein Frauenabteil. Männer sollten dort nicht landen, werden aber im Zweifelsfall verlegen angelächelt. Fahrkarten kann man in jeder U-Bahnstation kaufen. Neben den Kartenterminals gibt es auch immer einen Schalter mit Menschen.

Taxis fahren ohne Taxameter. Ergo sollte man den Preis vorher ausmachen. Die Sparfüchse unter uns nutzen „Snapp!“. Vorausgesetzt, man hat eine iranische SIM-Karte gekauft, kann man sich diese App runter laden und fortan wie bei Uber Start- und Zielpunkte auf einer Karte eingeben. Irgend ein Fahrer nimmt sich dieses Angebots an und kommt in relativ kurzer Zeit zur Abholung. Vorteil: Die Preise stehen vorher schon fest (keine Verhandlung) und Orte müssen auch nicht erklärt werden, da sie auch schon festgelegt wurden. Frau kann theoretisch auch nur die Beförderung durch eine Frau wünschen. Nachteil: Die Autos der Fahrer sind oft alte Schäsen und haben meist keine Klimaanlage und die Fahrer können außer Farsi nichts. Kommunikation läuft also nur über das Schlaufon. Taxis haben dagegen oft bessere Autos und sprachgewandtere Fahrer.

Kleinbusse fahren wie in solchen Ländern üblich, feste Strecken und dann los, wenn sie voll sind.

Reisebusse fahren halbvoll los und laden unterwegs an gewissen Stellen noch Leute ein. Ebenso kann man jederzeit an der Strecke aussteigen. Vorher mit dem Fahrtbegleiter abkarteln.

Zug : Zu testen.

Unterkunft

Die Unterkünfte sind von variabler Qualität. Hotels sind meist Kästen aus den 70ern; hin und wieder sind kleine Oasen dabei. Baulich haben sie alle nicht den höchsten Stand. Wer mit Leuten in Kontakt kommen will, sollte (wie immer) in einem Hostel absteigen. Mit aktuell zwischen 10 und 25 € für ein Privatzimmer mit Bad sehr günstig. Hotels gibt es ab 26 € und sie sind damit auch sehr günstig. In „internationalen“ Hotels kann man Geldwechseln und in manchen wohl auch mit VISA/Master bezahlen. Darauf sollte man sich aber nicht verlassen. Manche Hostels bieten auch Zahlen mit Karte an. Wer weiß über was für Umwege die da dran kommen. Man sollte sich nicht drauf verlassen und Barzahlung geht immer.

Wasser

Die meisten Städte haben eine ordentliche öffentliche Wasservesorgung, die für trinkbares Wasser sorgt. Stellenweise ist mal kein Chlor drin. Man muss sich aber beim Zähneputzen und beim Duschen keine Sorgen machen. Die Trinkwasserspender, die es Allerorten gibt, konnten wir bislang ohne Reue nutzen. Höchstwahrscheinlich geben sie das Wasser nur gekühlt und direkt aus der Leitung ab. Aufpassen, das sagt der gesunde Ingenieursverstand, sollte man auf dem Lande in kleinen Dörfern – also ohne groß angelegte Wasserversorgung. Natürlich kann man auch überall günstig Wasser in Plastikflaschen kaufen. Ein Wiederbefüllen tut der Umwelt gut.

Essen

Das Essen ist gut und in aller Regel hygienisch einwandfrei. Natürlich sollte immer der gesunde Blick walten. Von Majonäse und Softeis würde ich zumindest die Finger lassen. Neben Restaurants gibt es Kebaberias und den üblichen Pizza, Pasta, Burger, KFC und Pommes-Schmarrn. Das ist aber kein persisches Essen. Da sollte man dann doch in „bessere“ Restaurants gehen, die im übrigen auch nicht sonderlich teuer sind. Wir konnten uns regelmäßig eine Portion teilen (so groß waren die) und gingen am Ende mit 5-8 € heraus. So sonderlich vielfältig ist das persische Essen bisher nicht oder wir haben es nicht richtig angestellt. Sonderlich viel weiter als Reis, Kofter, Gemüse und Kebab sind wir nicht gekommen. Wir versuchen es weiter!

Illegale Fotos und Polizei

Die Polizei sollte man nicht unterschätzen. Zumindest nicht die Zeit, die sie im Vergleich zu uns Touristen hat. Man sollte also nichts falsches Fotografieren oder generell irgendwas anstellen, was gegen das Gesetz wäre. Wir haben es ausprobiert und dabei 7 Stunden und einen angefangenen Tag verloren. In meinem Fall war es ein unbedeutender Stromkasten an einem öffentlichen Gebäude. Am Ende wurde mir der Pass und das Mobiltelefon für die genannte Zeit konfisziert. Übernachten durfte ich weiterhin im Hotel. Am Ende war alles recht freundlich, die Zeit war aber dennoch hin und ohne Mobiltelefon auch recht langweilig. Zwischen den Gesprächen verging immer recht viel Zeit. In der Polizeistelle selbst geht es zwar wie im Taubenschlag zu, aber die Beamten machen Dienst nach Vorschrift. Im Zweifel erst mal Tee kochen, dann Akten wegräumen und dann erst um „Kundschaft“ Kümmern. Englisch geschweige den Deutsch sprechen vielleicht 3 Leute. Daher muss man sich schon recht aktiv durchwurschteln. Der Chef der Polizeistelle muss auch nicht mehr als Persisch können, denn das wichtigste ist, dass er die Islamische Republik korrekt vertritt. Also in religiösen Fragen korrekt ist.

Falls man mal selbst in so eine Situation kommt, hier mal was bei mir in Shiraz so passiert ist: Zunächst vergingen 2h, ehe ich an die richtige Stelle kam, wo wohl mein Pass und mein Mobiltelefon waren. Zwischenzeitlich wurde vermutlich der Inhalt meines Mobiltelefons geprüft. Dann wurde ich mit lästigen Unterbrechungen befragt, woher, wohin, wieso. Name, Adresse etc. Inhalte der Fotogalerie. Iraner auf Fotos und in WhatsApp wurden angerufen zur Verifikation von Informationen. Meta: Man will die Ehrlichkeit prüfen und ein wenig mit Zeit (es dauert) bestrafen. Besuche in Israel oder den USA muss man nicht abstreiten, das ist für den Iran OK und ja auch nicht verboten. Später kam es zum Interview mit dolmetschenden Beamten beim Polizeichef. Der schien Touristen nicht soo sehr zu mögen und hatte dann doch eher komische Fragen gestellt und doch irgendwie verlegen nach Verwertbarem gesucht. Meta: Man sucht nach Hinweisen auf Spionage. Da ich mich reuig und kooperativ gezeigt hatte, war recht klar, dass ich das unbeschadet überstehe. Nervig war aber dennoch die Ungewissheit. In dieser ließen sie mich auch gleich noch, denn meinen Pass sollte ich erst morgen erhalten; das Mobiltelefon gäbe es heute. Am nächsten Tag ging es nochmals zum Polizeichef ins Gebet mit dem dolmetschenden jungen Beamten. Das wurde dann eher eine Fragestunde, wie denn wohl die Deutschen allgemein zum Iran stehen, wie man die Waffenlieferungen nach Saudi Arabien und den Krieg im Jemen sieht. Was man selbst für eine Religion hat und wie man sie lebt, was man verdient. Und als Appell dass man selbst die islamischen Werte (nicht Religion) leben sollte – die ja den christlichen nicht unähnlich sind. Nach etwa einer Stunde gab es den Pass auch zurück und noch Wünsche für eine gute Weiterreise. Man sei in Shiraz jederzeit wieder willkommen. Tja sowas.

Hannah B. und die geheime Chemnitzer U-Bahn

Es klingt wie aus einem schlechten amerikanischen, immer wieder aufgewärmten, Märchen und fand doch vor der eigenen Haustür statt: die zehnjähriger Hannah B. Fiel auf dem Heimweg von der Schule zu den berühmten Kletterfelsen einem Eichhörnchen folgend in das plötzlich, zur Grabung des einer zweiten Bazillenröhre, ausgehobene Loch zwischen dem Hauptbahnhof und dem Chemnitzer Stadtteil Sonnenberg.

Und damit ließ sich nicht mehr unter Verschluss halten, was doch bei genauer Beobachtung längst offensichtlich war: In Chemnitz gibt es eine geheime U-Bahn. Träumten wir doch schon immer von einer schnellen Verbindung zwischen Lokomov und Haamit ohne an der Zenti 4000 Rentnern zu begegnen, so ist dieser Traum wahr. Nur irgendwie anders.

Diese stammt aus den finsteren Zeiten des vergangenen Jahrhunderts und obwohl es bis dato keinerlei Beweise gibt, keine Baupläne, keine offiziellen Beschlüsse und keine Fotos, deuten doch es ein paar Indizien auf das versteckte Verkehrsnetz hin. Noch heute ist im CVAG Plan von einem „speziellen Transportsystem“ namens AliTa die Rede, das nicht näher erklärt wird. Auch auf Stadtratsanfragen hin wird bis heute verschwiegen, wo die Linie 2 im ÖPNV System dieser Stadt den fährt. Die geheime U-Bahn war nicht dauerhaft in Betrieb: Sie wurde zuvorderst für den Transport von Waffen zum Bahnhof und ferner für Notfälle und Krisen gebaut. Eine wichtige Rolle spielte sie während des Zweiten Weltkrieges: Die Schächte und Stationen dienten als größter Luftschutzbunker

Ein eingleisiges System sollte die wichtigsten Macht-und Industriezentren der Stadt verbinden und eben hohe Regierungsbeamte jederzeit schnellstmöglich und heimlich aus der Stadt evakuiert werden. Die menschenscheue BabaLu erwog daher schon zu Beginn ihrer ewigen Amtszeit den Ausbau des Systems bis nach Kleinolbersdorf-Altenhain.

Ein Grund, warum die Stadt Chemnitz sich so lange weigerte , die Bazillenröhre bis zum Sonnenberg fortzusetzen und eine zweite Parallelröhre anzulegen, ist die äußerst wahrscheinliche Kreuzung mit der U-Bahn. Diese selbst stammt eben aus einer Zeit, der gewisse und nicht besonders leise Chemnitzer jetzt noch frönen und das passt nun gar nicht zur Wisch-und Weg-Imagekampagne „Chemnitz ist weder grau noch braun“. Dabei ist es an einem Markttag mit Obst-und Gärtnerstäden von oben betrachtet doch einfach nur bunt und grau.

Dieselbe Begründung dürfte für die ewige Unbebauung des Contilochs gelten. Da war man sich ewig unsicher, wie beim Bau die U-Bahn umgangen werden könnte. Erst ein Umbau des Dresdner Platzes samt einer Rest-Wildfläche machte die Bebauung mit dem Technischen Rathaus möglich. Während normaler jeder kleine Spatenstich, auch der in den Sandkästen eines Kindergartens im benachbarten Lutherviertels publiziert wird, wurde den bedeutenden Grabungen der zweiten Fuswegstammstrecke zum jegliche öffentliche Nachricht verweigert. Denn oberstes Gebot: die Existenz der U-Bahn muss unter Verschluss bleiben.

Derweil die eingangs erwähnte Hannah B. glücklicherweise den sichtbaren Notausgang auf der Sonnenstraße fand und ihrer alleinerziehenden Mutter in der immer einspurigen Schlange im Ghetto-Netto-Einkauf aufgeregt davon erzählte, lauschten wir auf und begannen die Grabungen in unseren Erinnerungen.

„Auch du wirst entdecken, dass viele Wahrheiten, an die wir uns klammern, von unserem persönlichen Standpunkt abhängig sind.“ (Obi wan Kenobi, Star Wars).

Ein sehr betagter Herr berichtete uns eins von den geheimen Plänen und seinem Plattenbau über dem Notausgang. Er wusste auch von den Stationen, die wir nun zu rekonstruieren versuchen.

Gemutmaßte Streckenführung:
Sonnenstraßenkarree, mysteriöse Treppe von alten Mann gehört
Contiloch
Hauptbahnhof, die seltsame Zwischengeschossführung des Liftes zum WC und zu Gleis 14 weist ja irgendwie drauf hin.
Limbacher Str/Hartmannwerk-eingestürztes Haus“ Risse in der Wand, Loch in der Grundmauer: (Anwohner der Brückenbaustelle Hartmannstraße in Sicherheit gebracht, März 2010, Die Ursache, die zu den Gebäudeschäden führte, ist nach wie vor unklar.)
Kaßberggewölbe
Geheimer Tresor im Gunzenhauser, falls ihr es zur nächsten Museumsnacht mal hineinschafft, schaut euch genau um.
Endstation Industriemuseum
Mögliche Abzweigungen zum Bahnhof-Mitte oder in Richtung Tietz/Heutige Tiefgarage der Sparkasse denkbar

Wie wird es nun weitergehen. Auch unter Ausschluss der Öffentlichkeit sind Millioneninvestitionen angekündigt. Nicht von dem Dauergünstling und Hoffreund aus Regensburg. Sondern von einem, und das ist so überraschend wie unglaublich clever, jüdisch-iranischen Konsortium. Deren Bedingung ist nun eine bessere Anbindung der Restaurants Shalom und Safran. Darauf wären selbst die größten Aluhüte nicht gekommen.

OREO und Cookies sind keine Essorten

Sommer ist die Zeit des Eises. Wer nichts davon versteht oder keine Alternativen hat, nimmt sich Stieleis von Langnese oder Nestle/Schöller oder lässt sich von Eisverkäufern welches aus dem Industriees-Behälter servieren. Wer es besser machen will oder das Eismacher-Handwerk schätzt, geht zur Eisdiele. Am besten die vom ausgewanderten Italiener. Denn wirklich gutes Speiseeis schmeckt besser als der Rest und hat dazu eine ganz spezielle Konsistenz. Die lässt sich leider auch nicht ganz toll konservieren, wesswegen Industrieeis aus Containern da nie ran kommt. Es geht um die kremigkeit und darum, möglichst wenig Kristalle noch drin zu haben. Dazu muss eine Emulsion gebildet werden. Durch Schlagen bzw. Rühren bei gleichzeitiger Kühlung der Grundmasse und der Lebensmittelzusatzstoffe entsteht eine Creme ohne Eiskristall­bildung. Die Struktur muss so fest sein, dass es auch bei angenehmer Kälte nicht gleich zerläuft – aber schmilzt. Als wesentliche Richtungen gibt es Sorbet, Milcheis, Eiercremeeis, Sahneeis, Fruchteis. Alle werden unterschiedlich zusammengesetzt und haben ihre eigenen Difiizilitäten und optimalen Temperaturen. Man sieht also: Es gehört eine geiwisse Kunstfertigkeit dazu, gutes Eis zu produzieren. Das darf auch respektiert werden: Geht daher häufiger mal zu eurem lokalen Eismanufakturisten, und nicht an die Gefriertruhe.

Mein Problem mit Sorten

Ich aktzeptiere OREO, Cookies und After-Eight nicht als Eissorte. Immer wieder jedoch kommt man bei Eisdielen (die es selbst machen) daran vorbei. Und jedes Mal denke ich mir – will ich nicht. Dennoch verkauft sich das Zeug recht gut.

Ich bin jedoch der Meinung, Speiseeis sollte aus guten und natürlichen Produkten erzeugt werden und nicht aus „nach dem Maul des Konsumenten“ designten Insdustrieprodukten mit zich E-Nummern in der Zutatenliste.

Hat denn ernstaft jemand geglaubt, dass Oreo aus Mehl oder der Inhalt aus Milch besteht? Tut es beides nicht. Billiger Kakao, Backtriebmittel und Pal- und Kokusmfett. Zucker nicht vergessen. Es ist also ein typisches synthetisches Produkt, denn aus den genannten Fetten, Zucker und E-Zeug kann man praktisch alles herstellen. Sowas will/kann man doch nicht zu einem hochwertigen Handwerksprodukt verarbeiten.

Bei Cookies sind die amerikanischen Zuckerhäufchen gemeint, die ein bisschen Mehl und Schokolade enthalten. Das mag noch „natürlich von Mutti“ sein und wunderbar das infantile Lecker-Gen triggern. Aber die Kekse selbst sind doch qua Rezept die reinsten Zuckerhäufchen und für mich nicht mehr mit dem Konzept „Keks“ vereinbar. Daher möchte ich sowas auch nicht als Speiseeis serviert bekommen.

Bei After-Eight und Snickers, Duplo oder Raffaelo-Eis gilt im Prinzip das geschriebene von gerade. Es sind halt nach dem Maul designte Chemie-Industrie-Produkte.

So jetzt wisst ihr, warum ich eher Sorbet, Fruchteis oder eine Milch/Joghurt-Komposition zu mir nehme. Auch Schokolade ist ein wunderbares Produkt/Speiseeis. Vor allem, wenn es gemischt is.

Die Werbung für US-Eis

Und dann nervt mich regelmäßig noch die Werbung von Ben & Jerry’s Eis. Auch Cookies. Und so bröselig wie kein anderes. Nein, Nein, Nein … genau das will ich nicht. Bleibt mir fern mit dem Industriekäkse. Schon mal überlegt, wie Kekse im Wasser knakick bleiben? Chemie. Und richtig gute Gaumenreißer sind es zudem. Also geht lieber mal zum Hersteller in Eurer Fußgängerzone. Der freut sich, wenn er auch mal eine ganze Tupperschale verkaufen darf und bleibt dadurch am Leben.

Weichmacher

Zuletzt muss ich mich noch über zu weiches Speiseeis aufregen, wie man es von gewissen Herstellern regelmäßig findet. Zugegeben: Ich kaufe auch mal in der Frost-Abteilung eines örtlichen Superhändlers ein. Vor allem Vanilleeis, denn ich mache mir gerne mal meinen eigenen Affogato. Nur: es gibt irgendwie immer weniger Speiseeis im Container, das Stichfest ist. Also welches, wo man richtig mit Kraft rauskratzen muss. Stattdessen findet man zu oft eine weiche Pampe, die bei Minusgraden schon zu zerlaufen beginnt. „Sooo sahnig wie noch nie – Zerlaufen Sie mit dem Eis“ .. so der Werbespruch. Das ist wohl der Grund dafür. Aber auch hier hat MAN wieder mal keine Ahnung, wie oder was ein korrektes Speiseeis ist/sein soll. Es soll eben nicht sooo sahnig und zerschmelzend sein, dass am Ende nur noch Soße da ist. Nein, es soll langsam schmelzen und frisch aus der Tiefkühltrue soll es richtig Mühe machen, eine Kugel daraus zu extrahieren.

Eise die nix taugen:
* alle außer
Eise die was taugen:
* REWE exzelenz
* Bruno GELATO

Fahrrad mit Licht

Waaah, heute muss ich mich aufregen. Immer wieder eigentlich. Denn immer wieder begegne ich Fahrradfahrern, die zwar wunderbar starkes Licht anhaben, aber nicht in der Lage sind, korrekt damit zu leuchten. Nebenbei und fast schlimmer sind natürlich diejenigen, die ganz ohne Licht herumfahren.

Was ist das Problem?

Seit wir LED-Fahrradbeleuchtung haben ist es ein wenig krass auf den Straßen geworden. Im Gegensatz zu den guten alten Glühlampen kann eine LED in einem Fahrradscheinwerfer ein vielfaches des Lichtstroms rauswerfen. Soweit, so schön. Man sieht als Fahrradfahrer mehr. Zum Problem wird es dann, wenn der Schein der Lampe auf Kopfhöhe der Passanten (ob Rad oder zu Fuß) gerichtet ist. Dann sieht der Betroffene zwar sehr gut und kann auch die erstarrten Gesichtszüge des Passanten gut erkennen, der Passant kann aber vor lauter Licht gar nichts mehr sehen. Und das ist eigentlich eine Plage.

Lösung

Die Lösung des Problems ist ganz einfach: Der Scheinwerfer des Fahrrads muss nur nach unten auf die Straße gerichtet werden. Da wo er auch hin leuchten soll. Ganz im Sinne des, vom Auto bekannten, Abblendlichts.